1 /**
2  * libdmtx - Data Matrix Encoding/Decoding Library
3  * Copyright 2010 Mike Laughton. All rights reserved.
4  *
5  * See LICENSE file in the main project directory for full
6  * terms of use and distribution.
7  *
8  * Contact: Mike Laughton <mike@dragonflylogic.com>
9  *
10  * \file multi_test.h
11  */
12 
13 #include <SDL/SDL.h>
14 #include "../../dmtx.h"
15 
16 #define max(N,M) ((N > M) ? N : M)
17 #define min(N,M) ((N < M) ? N : M)
18 #define OPPOSITE_SIGNS(a,b) (a != 0 && b != 0 && ((a > 0) != (b > 0)))
19 
20 #define LOCAL_SIZE            64
21 #define MAXIMA_SORT_MAX_COUNT  8
22 #define ANGLE_SORT_MAX_COUNT   8
23 #define TIMING_SORT_MAX_COUNT  8
24 
25 #define NFFT                  64 /* FFT input size */
26 #define HOUGH_D_EXTENT        64
27 #define HOUGH_PHI_EXTENT     128
28 
29 /* Layout constants */
30 #define CTRL_COL1_X          380
31 #define CTRL_COL2_X          445
32 #define CTRL_COL3_X          510
33 #define CTRL_COL4_X          575
34 #define CTRL_ROW1_Y            0
35 #define CTRL_ROW2_Y           65
36 #define CTRL_ROW3_Y          130
37 #define CTRL_ROW4_Y          195
38 #define CTRL_ROW5_Y          260
39 #define CTRL_ROW6_Y          325
40 #define CTRL_ROW7_Y          390
41 
42 #define MODULE_LOW             0
43 #define MODULE_HIGH            1
44 #define MODULE_UNKNOWN         2
45 
46 #define RotateCCW(N) ((N < 8) ? (N << 1) : 1)
47 #define RotateCW(N)  ((N > 1) ? (N >> 1) : 8)
48 
49 typedef struct UserOptions_struct {
50    const char *imagePath;
51 } UserOptions;
52 
53 typedef struct AppState_struct {
54    int         windowWidth;
55    int         windowHeight;
56    int         activeExtent;
57    DmtxImage   *imgActive;
58    DmtxImage   *imgFull;
59    DmtxImage   *dmtxImage;
60    DmtxBoolean autoNudge;
61    int         displayEdge;
62    DmtxBoolean displayVanish;
63    DmtxBoolean displayTiming;
64    DmtxBoolean displayZXings;
65    DmtxBoolean printValues;
66    Sint16      imageLocX;
67    Sint16      imageLocY;
68    Sint16      imageOffsetX; /* X offset of right-handed image origin from screen origin */
69    Sint16      imageOffsetY; /* Y offset of right-handed image origin from screen origin */
70    Sint16      localOffsetX; /* X offset of active area */
71    Sint16      localOffsetY; /* Y offset of active area */
72    Uint8       leftButton;
73    Uint8       rightButton;
74    Uint16      pointerX;
75    Uint16      pointerY;
76    DmtxBoolean quit;
77    SDL_Surface *picture;
78    SDL_Surface *screen;
79    SDL_Surface *local;
80    SDL_Surface *localTmp;
81 } AppState;
82 
83 typedef enum {
84    DmtxEdgeVertical,
85    DmtxEdgeBackslash,
86    DmtxEdgeHorizontal,
87    DmtxEdgeSlash
88 } DmtxEdgeType;
89 
90 typedef enum {
91    DmtxOctantTop         = 0x01,
92    DmtxOctantLeft        = 0x01 << 1,
93    DmtxOctantBottom      = 0x01 << 2,
94    DmtxOctantRight       = 0x01 << 3,
95    DmtxOctantTopLeft     = (DmtxOctantTop | DmtxOctantLeft),
96    DmtxOctantBottomLeft  = (DmtxOctantBottom | DmtxOctantLeft),
97    DmtxOctantBottomRight = (DmtxOctantBottom | DmtxOctantRight),
98    DmtxOctantTopRight    = (DmtxOctantTop | DmtxOctantRight)
99 } DmtxOctantType;
100 
101 typedef struct DmtxValueGrid_struct DmtxValueGrid;
102 struct DmtxValueGrid_struct {
103    int width;
104    int height;
105    int type;
106    int *value;
107    DmtxValueGrid *ref;
108 };
109 
110 typedef struct DmtxSobel_struct DmtxSobel;
111 struct DmtxSobel_struct {
112    DmtxValueGrid *v;
113    DmtxValueGrid *b;
114    DmtxValueGrid *h;
115    DmtxValueGrid *s;
116 };
117 
118 typedef struct DmtxAccel_struct DmtxAccel;
119 struct DmtxAccel_struct {
120    DmtxValueGrid *vv;
121    DmtxValueGrid *vb;
122    DmtxValueGrid *hb;
123    DmtxValueGrid *hh;
124    DmtxValueGrid *hs;
125    DmtxValueGrid *vs;
126 };
127 
128 struct ZeroCrossing_struct {
129    int iCol;
130    int iRow;
131    int mag;
132    double x;
133    double y;
134 };
135 typedef struct ZeroCrossing_struct ZeroCrossing;
136 
137 typedef struct DmtxHoughBucket_struct DmtxHoughBucket;
138 struct DmtxHoughBucket_struct {
139    int phi;
140    int d;
141    int val;
142 };
143 
144 typedef struct DmtxHoughLocal_struct DmtxHoughLocal;
145 struct DmtxHoughLocal_struct {
146    int xOrigin;
147    int yOrigin;
148    int dOrigin[128];
149    int bucket[64][128]; /* [rows][cols] */ /* later change to 65 */
150 };
151 
152 typedef struct DmtxHough_struct DmtxHough;
153 struct DmtxHough_struct {
154    int rows;
155    int cols;
156    int count;
157    DmtxHoughLocal *line;
158    DmtxHoughLocal *maxima;
159    DmtxHoughLocal *vanish;
160 };
161 
162 typedef struct HoughMaximaSort_struct {
163    int count;
164    int mag[MAXIMA_SORT_MAX_COUNT];
165 } HoughMaximaSort;
166 
167 typedef struct VanishPointSort_struct {
168    int count;
169    DmtxHoughBucket bucket[ANGLE_SORT_MAX_COUNT];
170 } VanishPointSort;
171 
172 typedef struct Timing_struct {
173    int phi;
174    double shift;
175    double period;
176    double mag;
177 } Timing;
178 
179 struct DmtxTimingSort_struct {
180    int count;
181    Timing timing[TIMING_SORT_MAX_COUNT];
182 };
183 typedef struct DmtxTimingSort_struct DmtxTimingSort;
184 
185 typedef struct DmtxOrient_struct DmtxOrient;
186 struct DmtxOrient_struct {
187 /* add supporting values used to build tranformation matrices here */
188    DmtxMatrix3 raw2fitLocal;
189    DmtxMatrix3 raw2fit;
190    DmtxMatrix3 fit2rawLocal;
191    DmtxMatrix3 fit2raw;
192 };
193 
194 typedef struct AlignmentGrid_struct {
195    int rowCount;
196    int colCount;
197    DmtxMatrix3 raw2fitActive;
198    DmtxMatrix3 raw2fitFull;
199    DmtxMatrix3 fit2rawActive;
200    DmtxMatrix3 fit2rawFull;
201 } AlignmentGrid;
202 
203 typedef struct GridRegion_struct {
204    AlignmentGrid grid;
205    int x;
206    int y;
207    int width;
208    int height;
209    int sizeIdx;
210    int onColor;
211    int offColor;
212    int finderSides;
213    int contrast;
214 } GridRegion;
215 
216 typedef struct RegionLines_struct {
217    int gridCount;
218    Timing timing;
219    double dA, dB;
220    DmtxRay2 line[2];
221 } RegionLines;
222 
223 struct DmtxRegionSides_struct {
224    DmtxRay2 top;
225    DmtxRay2 left;
226    DmtxRay2 bottom;
227    DmtxRay2 right;
228 };
229 typedef struct DmtxRegionSides_struct DmtxRegionSides;
230 
231 /* All values in GridRegionGrowth should be negative because list
232  * is combined with the positive values of DmtxSymbolSize enum */
233 typedef enum {
234    GridRegionGrowthUp       = -5,
235    GridRegionGrowthLeft     = -4,
236    GridRegionGrowthDown     = -3,
237    GridRegionGrowthRight    = -2,
238    GridRegionGrowthError    = -1
239 } GridRegionGrowth;
240 
241 typedef enum {
242    DmtxBarNone     = 0x00,
243    DmtxBarTiming   = 0x01 << 0,
244    DmtxBarFinder   = 0x01 << 1,
245    DmtxBarInterior = 0x01 << 2,
246    DmtxBarExterior = 0x01 << 3
247 } DmtxBarType;
248 
249 /* Only used internally */
250 typedef struct ColorTally_struct {
251    int evnCount;
252    int oddCount;
253    int evnColor;
254    int oddColor;
255 } ColorTally;
256 
257 struct StripStats_struct {
258    int jumps;
259    int surprises;
260    int finderErrors;
261    int timingErrors;
262    int contrast;
263    int finderBest;
264    int timingBest;
265 };
266 typedef struct StripStats_struct StripStats;
267 
268 struct DmtxCallbacks_struct {
269    void (*dmtxValueGridCallback)(DmtxValueGrid *, int);
270    void (*zeroCrossingCallback)(ZeroCrossing, int);
271    void (*dmtxHoughLocalCallback)(DmtxHoughLocal *, int);
272    void (*vanishPointCallback)(VanishPointSort *, int);
273    void (*timingCallback)(Timing *, Timing *, int);
274    void (*gridCallback)(AlignmentGrid *, int);
275    void (*perimeterCallback)(GridRegion *, DmtxDirection, DmtxBarType);
276 };
277 typedef struct DmtxCallbacks_struct DmtxCallbacks;
278 
279 typedef struct DmtxVectorPair_struct DmtxVectorPair;
280 struct DmtxVectorPair_struct {
281    DmtxVector2 a;
282    DmtxVector2 b;
283 };
284 
285 typedef struct DmtxVanishCorners_struct DmtxVanishCorners;
286 struct DmtxVanishCorners_struct {
287    unsigned char zone;
288    DmtxRay2 lineA; /* XXX consider switching to DmtxVectorPair later? */
289    DmtxRay2 lineB;
290 };
291 
292 struct DmtxDecode2_struct {
293    DmtxImage     *image;
294    DmtxSobel     *sobel;
295    DmtxAccel     *accel;
296    DmtxHough     *hough;
297    DmtxVanishCorners corners[64][128]; /* XXX temporary location */
298    DmtxCallbacks  fn;
299 };
300 typedef struct DmtxDecode2_struct DmtxDecode2;
301 
302 /* Application level functions */
303 DmtxPassFail HandleArgs(UserOptions *opt, int *argcp, char **argvp[]);
304 AppState InitAppState(void);
305 DmtxImage *CreateDmtxImage(SDL_Surface *sdlImage);
306 void AddFullTransforms(AlignmentGrid *grid);
307 SDL_Surface *SetWindowSize(int windowWidth, int windowHeight);
308 void captureLocalPortion(SDL_Surface *local, SDL_Surface *localTmp,
309       SDL_Surface *picture, SDL_Surface *screen, AppState *state, SDL_Rect imageLoc);
310 DmtxPassFail HandleEvent(SDL_Event *event, AppState *state,
311       SDL_Surface *picture, SDL_Surface **screen);
312 DmtxPassFail NudgeImage(int windowExtent, int pictureExtent, Sint16 *imageLoc);
313 /*static void WriteDiagnosticImage(DmtxDecode *dec, char *imagePath);*/
314 
315 /* Image processing functions */
316 DmtxPassFail dmtxRegion2FindNext(DmtxDecode2 *dec);
317 DmtxPassFail OrientRegion(DmtxOrient *orient, DmtxHoughBucket v0, DmtxHoughBucket v1, DmtxDecode2 *dec);
318 double UncompactOffset(double d, int phiIdx, int extent);
319 void AddToVanishPointSort(VanishPointSort *sort, DmtxHoughBucket bucket);
320 VanishPointSort dmtxFindVanishPoints(DmtxHoughLocal *vHough);
321 void AddToMaximaSort(HoughMaximaSort *sort, int maximaMag);
322 DmtxHoughBucket GetAngleSumAtPhi(DmtxHoughLocal *local, int phi);
323 void AddToTimingSort(DmtxTimingSort *sort, Timing timing);
324 DmtxTimingSort dmtxFindGridTiming(DmtxHoughLocal *local, VanishPointSort *sort);
325 DmtxRay2 HoughCompactToRay(int phi, double d);
326 DmtxPassFail dmtxBuildGridFromTimings(AlignmentGrid *grid, Timing vp0, Timing vp1);
327 StripStats GenStripPatternStats(unsigned char *strip, int stripLength, int startState, int contrast);
328 GridRegion NudgeStripLimits(GridRegion *region, DmtxDirection side, int nudgeStyle);
329 
330 DmtxPassFail dmtxFindRegionWithinGrid(GridRegion *region, AlignmentGrid *grid, DmtxHoughLocal *local, DmtxDecode *dec, DmtxCallbacks *fn);
331 int dmtxReadModuleColor(DmtxImage *img, AlignmentGrid *grid, int symbolRow, int symbolCol, int colorPlane);
332 DmtxBarType TestSideForPattern(GridRegion *region, DmtxImage *img, DmtxDirection side, int offset);
333 DmtxPassFail RegionExpand(GridRegion *region, DmtxDirection dir, DmtxHoughLocal *local, DmtxCallbacks *fn);
334 int dmtxGetSizeIdx(int a, int b);
335 DmtxPassFail RegionUpdateCorners(DmtxMatrix3 fit2raw, DmtxMatrix3 raw2fit, DmtxVector2 p00, DmtxVector2 p10, DmtxVector2 p11, DmtxVector2 p01);
336 DmtxPassFail dmtxDecodeSymbol(GridRegion *region, DmtxDecode *dec);
337 DmtxPassFail GetOnOffColors(GridRegion *region, const DmtxDecode *dec, int *onColor, int *offColor);
338 ColorTally GetTimingColors(GridRegion *region, const DmtxDecode *dec, int colBeg, int rowBeg, DmtxDirection dir);
339 
340 /* Process visualization functions */
341 void ValueGridCallback(DmtxValueGrid *valueGrid, int id);
342 void ZeroCrossingCallback(ZeroCrossing zXing, int id);
343 void HoughLocalCallback(DmtxHoughLocal *hough, int id);
344 void VanishPointCallback(VanishPointSort *vPoints, int id);
345 void TimingCallback(Timing *timing0, Timing *timing1, int id);
346 void GridCallback(AlignmentGrid *grid, int id);
347 void PerimeterCallback(GridRegion *region, DmtxDirection side, DmtxBarType type);
348 
349 void BlitSobelGrid(SDL_Surface *screen, DmtxValueGrid *cache, int x, int y, int screenY, int screenX);
350 void BlitHoughLocal(SDL_Surface *screen, DmtxHoughLocal *hough, int screenY, int screenX);
351 void ShowActiveRegion(SDL_Surface *screen, SDL_Surface *active);
352 void BlitActiveRegion(SDL_Surface *screen, SDL_Surface *active, int zoom, int screenY, int screenX);
353 Uint32 GetPixel(SDL_Surface *surface, int x, int y);
354 void PutPixel(SDL_Surface *surface, int x, int y, Uint32 color);
355 int RayIntersect(double *t, DmtxRay2 p0, DmtxRay2 p1);
356 int IntersectBox(DmtxRay2 ray, DmtxVector2 bb0, DmtxVector2 bb1, DmtxVector2 *p0, DmtxVector2 *p1);
357 void DrawActiveBorder(SDL_Surface *screen, int activeExtent);
358 void DrawLine(SDL_Surface *screen, int baseExtent, int screenX, int screenY, int phi, double d, int displayScale, Uint32 color);
359 void DrawVanishingPoints(SDL_Surface *screen, VanishPointSort *sort, int screenY, int screenX);
360 void DrawTimingDots(SDL_Surface *screen, Timing *timing, int screenY, int screenX);
361 void DrawNormalizedRegion(SDL_Surface *screen, DmtxImage *img, AlignmentGrid *grid, AppState *state, int screenY, int screenX);
362 Sint16 Clamp(Sint16 x, Sint16 xMin, Sint16 extent);
363 void DrawSymbolPreview(SDL_Surface *screen, DmtxImage *img, AlignmentGrid *grid, AppState *state, int screenY, int screenX);
364 void DrawPerimeterPatterns(SDL_Surface *screen, GridRegion *region, AppState *state, DmtxDirection side, DmtxBarType type);
365 void DrawPerimeterSide(SDL_Surface *screen, int x00, int y00, int x11, int y11, int dispModExtent, DmtxDirection side, DmtxBarType type);
366 
367 /* dmtxvaluegrid.c */
368 DmtxValueGrid *dmtxValueGridCreate(int width, int height, int type, DmtxValueGrid *ref);
369 DmtxPassFail dmtxValueGridDestroy(DmtxValueGrid **valueGrid);
370 int dmtxValueGridGetWidth(DmtxValueGrid *valueGrid);
371 int dmtxValueGridGetHeight(DmtxValueGrid *valueGrid);
372 int dmtxValueGridGetValue(DmtxValueGrid *valueGrid, int x, int y);
373 
374 /* dmtxsobel.c */
375 DmtxSobel *SobelCreate(DmtxImage *img);
376 DmtxPassFail SobelDestroy(DmtxSobel **sobel);
377 DmtxPassFail SobelPopulate(DmtxDecode2 *dec);
378 
379 DmtxAccel *AccelCreate(DmtxSobel *sobel);
380 DmtxPassFail AccelDestroy(DmtxAccel **accel);
381 DmtxPassFail AccelPopulate(DmtxDecode2 *dec);
382 DmtxPassFail AccelPopulateLocal(DmtxValueGrid *acc);
383 
384 /* dmtxdecode2.c */
385 DmtxDecode2 *dmtxDecode2Create();
386 DmtxPassFail dmtxDecode2Destroy(DmtxDecode2 **dec);
387 void PopulateVanishBounds(DmtxDecode2 *dec);
388 DmtxVanishCorners GetVanishCorners(int d, int phi);
389 int GetZone(int phiFull, double *distance);
390 DmtxVectorPair GetZoneCornerLocs(DmtxOctantType zone);
391 DmtxPassFail dmtxDecode2SetImage(DmtxDecode2 *dec, DmtxImage *img);
392 DmtxPassFail decode2ReleaseCacheMemory(DmtxDecode2 *dec);
393 
394 /* dmtxhough.c */
395 DmtxHough *HoughCreate(int cols, int rows);
396 DmtxPassFail HoughDestroy(DmtxHough **grid);
397 DmtxPassFail HoughPopulate(DmtxDecode2 *dec);
398 DmtxPassFail LineHoughAccumulate(DmtxHoughLocal *lhRegion, DmtxDecode2 *dec);
399 DmtxPassFail MaximaHoughAccumulate(DmtxHoughLocal *mhRegion, DmtxHoughLocal *lhRegion, DmtxDecode2 *dec);
400 int GetMaximaWeight(DmtxHoughLocal *lhRegion, int phi, int d);
401 DmtxPassFail VanishHoughAccumulate(DmtxHoughLocal *lhRegion, DmtxHoughLocal *vhRegion);
402 int GetVanishBucket(int phiBucket, int phiCompare, int dCompare);
403 ZeroCrossing GetZeroCrossing(DmtxValueGrid *accel, int iCol, int iRow);
404 ZeroCrossing SetZeroCrossingFromIndex(DmtxValueGrid *accel, int aCol, int aRow, double smidg);
405 DmtxPassFail HoughLocalAccumulateEdge(DmtxHoughLocal *local, int phi, ZeroCrossing edge);
406 double HoughGetLocalOffset(double xLoc, double yLoc, int phi);
407 
408 extern AppState gState;
409