forked from golanlevin/QR_STENCILER
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Utils.pde
156 lines (131 loc) · 4.42 KB
/
Utils.pde
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Author: "Golan Levin" <[email protected]>, 01 August, 2011
//================================================================
void copyBlackAndWhiteImageFromPImage (PImage img) {
for (int i=0; i<nPixels; i++) {
blackAndWhiteImage[i] = img.pixels[i];
}
}
//===============================================================
void copyBufferToScreen(color[] imageBuffer, int nPix) {
// Note: no safety checks here.
loadPixels();
for (int i=0; i<nPix; i++) {
pixels[i] = imageBuffer[i];
}
updatePixels();
}
//===============================================================
void computeBlackAndWhiteInverseBuffer (color[] srcBuffer, color[] dstBuffer, int nPix) {
for (int i=0; i<nPix; i++) {
if (srcBuffer[i] == black) {
dstBuffer[i] = white;
}
else {
dstBuffer[i] = black;
}
}
}
//===============================================================
void binarizeTheImage (color[] bufferToProcess, int bufW, int bufH) {
// We clobber the image to ensure that .JPG artifacts don't confuse us.
// This forces pixels to pure black and pure white.
int binarizationThreshold = 127;
for (int y=0; y<bufH; y++) {
for (int x=0; x<bufW; x++) {
int index = y*bufW + x;
color c = bufferToProcess[index];
float bri = brightness(c);
if (bri < binarizationThreshold) {
bufferToProcess[index] = black;
}
else {
bufferToProcess[index] = white;
}
}
}
}
//===============================================================
int computeGridSize (color[] qrImageBuffer, int qrImageW, int qrImageH) {
// calculate the size of the QR code's grid units.
// we know that the first thing is a black square which is 7 units wide.
// use this information to automatically calculate the number of pixels per unit.
int marginX = 0;
int marginY = 0;
color searchColor = black;
if (DO_WHITE_PAINT_STENCIL){
marginX = inverseMargin+1;
marginY = inverseMargin+1;
searchColor = white;
}
boolean bFoundFirstSearchColorPixel = false;
boolean bColorHasntChangedSinceIFoundTheFirstSearchColorPixel = true;
int searchColorLocStartX = -1;
int searchColorLocEndX = -1;
int searchColorLocY = -1;
for (int y = marginY; y < (qrImageH-marginY); y++) {
for (int x = marginX; x < (qrImageW-marginX); x++) {
int index = y*qrImageW + x;
color someCol = qrImageBuffer[index];
if ((someCol == searchColor) && (bFoundFirstSearchColorPixel == false)) {
bFoundFirstSearchColorPixel = true;
searchColorLocStartX = x;
searchColorLocY = y;
}
if (y == searchColorLocY) { // if we are still in the same row
if (bColorHasntChangedSinceIFoundTheFirstSearchColorPixel) {
if (someCol != searchColor) {
bColorHasntChangedSinceIFoundTheFirstSearchColorPixel = false;
}
else {
searchColorLocEndX = x;
}
}
}
}
}
if (bFoundFirstSearchColorPixel && (searchColorLocStartX > -1) && (searchColorLocEndX > -1)) {
int distance = 1 + searchColorLocEndX - searchColorLocStartX; // +1 corrects off-by-one err
int gridSize = distance / 7; // fixed.
return gridSize;
}
println ("Error determining QR code grid size. Is your image a valid QR code?");
return -1;
}
//===============================================================
void handleInverseStencil(){
if (DO_WHITE_PAINT_STENCIL) {
// put a narrow margin around everything
int m = inverseMargin;
for (int y=0; y<QR.height; y++) {
for (int x=0; x<m; x++) {
int index = y*QR.width + x;
blackAndWhiteImage[index] = black;
}
for (int x=(QR.width-m); x<QR.width; x++) {
int index = y*QR.width + x;
blackAndWhiteImage[index] = black;
}
}
for (int y=0; y<m; y++) {
for (int x=0; x<QR.width; x++) {
int index = y*QR.width + x;
blackAndWhiteImage[index] = black;
}
for (int x=0; x<QR.width; x++) {
int index = (QR.height-1-y)*QR.width + x;
blackAndWhiteImage[index] = black;
}
}
// invert the image for further processing
for (int y=0; y<QR.height; y++) {
for (int x=0; x<QR.width; x++) {
int index = y*QR.width + x;
if (blackAndWhiteImage[index] == black){
blackAndWhiteImage[index] = white;
} else {
blackAndWhiteImage[index] = black;
}
}
}
}
}