File: dmtxdecode2.c

package info (click to toggle)
libdmtx 0.7.7-1.2
  • links: PTS
  • area: main
  • in suites: sid, trixie
  • size: 2,100 kB
  • sloc: ansic: 10,519; sh: 253; makefile: 154; perl: 28
file content (281 lines) | stat: -rw-r--r-- 5,833 bytes parent folder | download | duplicates (3)
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/**
 * libdmtx - Data Matrix Encoding/Decoding Library
 * Copyright 2010 Mike Laughton. All rights reserved.
 *
 * See LICENSE file in the main project directory for full
 * terms of use and distribution.
 *
 * Contact: Mike Laughton <mike@dragonflylogic.com>
 *
 * \file dmtxdecode2.c
 */

#include <math.h>
#include <assert.h>
#include "../../dmtx.h"
#include "multi_test.h"

/**
 *
 *
 */
DmtxDecode2 *
dmtxDecode2Create(DmtxImage *img)
{
   DmtxDecode2 *dec;

   dec = (DmtxDecode2 *)calloc(1, sizeof(DmtxDecode2));
   if(dec == NULL)
      return NULL;

   PopulateVanishBounds(dec);

   return dec;
}

/**
 *
 *
 */
DmtxPassFail
dmtxDecode2Destroy(DmtxDecode2 **dec)
{
   if(dec == NULL || *dec == NULL)
      return DmtxFail;

   decode2ReleaseCacheMemory(*dec);

   free(*dec);
   *dec = NULL;

   return DmtxPass;
}

#define RETURN_FAIL_IF(c) \
   if(c) { \
      decode2ReleaseCacheMemory(dec); \
      return DmtxFail; \
   }

/**
 *
 *
 */
void
PopulateVanishBounds(DmtxDecode2 *dec)
{
   int d, phi;

   for(phi = 0; phi < 128; phi++)
      for(d = 0; d < 64; d++)
         dec->corners[d][phi] = GetVanishCorners(d, phi);
}

/**
 *
 *
 */
DmtxVanishCorners
GetVanishCorners(int d, int phi)
{
   DmtxVanishCorners vBound;
   DmtxVectorPair locs, dirs;
   int zone;
   int dFull, phiFull;
   double l, phiRad, bucketRad;
   DmtxVector2 v;

   dFull = d - 32;
   phiFull = (dFull < 0) ? phi + 128 : phi;
   assert(phiFull >= 0 && phiFull < 256);
   phiRad = phi * (M_PI/128.0);

   /* Infinity */
   if(dFull == 0)
   {
      zone = GetZone(phiFull, NULL);
      locs = GetZoneCornerLocs(zone);

      dirs.a.X = dirs.b.X = cos(phiRad); /* XXX does phiRad point in this direction, or right angle? */
      dirs.a.Y = dirs.b.Y = sin(phiRad);
   }
   else
   {
      bucketRad = abs(dFull) * (M_PI/96.0);
      l = 32/tan(bucketRad);
      zone = GetZone(phiFull, &l);
      locs = GetZoneCornerLocs(zone);

      v.X = l * cos(phiRad);
      v.Y = l * sin(phiRad); /* XXX remember phiRad may not point in direction you think */

      dmtxVector2Sub(&dirs.a, &v, &locs.a);
      dmtxVector2Sub(&dirs.b, &v, &locs.b);

      dmtxVector2Norm(&dirs.a); /* I think this is necessary */
      dmtxVector2Norm(&dirs.b);
   }

   vBound.zone = zone;
   vBound.lineA.p = locs.a;
   vBound.lineA.v = dirs.a;
   vBound.lineB.p = locs.b;
   vBound.lineB.v = dirs.b;

   return vBound;
}

/**
 *
 *
 */
int
GetZone(int phiFull, double *distance)
{
   int zone0 = 0;
   int zone1, zone2;
   double phiRad, xComp, yComp;

   if(phiFull < 32 || phiFull >= 224)
      zone1 = DmtxOctantTop;
   else if(phiFull < 96)
      zone1 = DmtxOctantLeft;
   else if(phiFull < 160)
      zone1 = DmtxOctantBottom;
   else
      zone1 = DmtxOctantRight;

   /* Orthagonal directions */
   if(phiFull == 0 || phiFull == 64 || phiFull == 128 || phiFull == 196)
      return (distance != NULL && *distance < 32.0) ? zone0 : zone1;

   if(phiFull < 64)
      zone2 = DmtxOctantTopLeft;
   else if(phiFull < 128)
      zone2 = DmtxOctantBottomLeft;
   else if(phiFull < 192)
      zone2 = DmtxOctantBottomRight;
   else
      zone2 = DmtxOctantTopRight;

   /* Non-orthagonal vanishing point at infinity */
   if(distance == NULL)
      return zone2;

   /* Must be a finite non-orthagonal vanishing point */
   phiRad = phiFull * (M_PI/128.0);
   xComp = fabs(32.0/cos(phiRad)); /* remember phiRad may not point in direction you think */
   yComp = fabs(32.0/sin(phiRad));

   if(*distance > max(xComp,yComp))
      return zone2;
   else if(*distance > min(xComp,yComp))
      return zone1;

   return zone0;
}

/**
 *
 *
 */
DmtxVectorPair
GetZoneCornerLocs(DmtxOctantType zone)
{
   const DmtxVector2 p00 = { 0.0, 0.0 }; /* should be { -32.0, -32.0 } ? */
   const DmtxVector2 p10 = { 1.0, 0.0 };
   const DmtxVector2 p11 = { 1.0, 1.0 };
   const DmtxVector2 p01 = { 0.0, 1.0 };
   DmtxVectorPair locs;

   switch(zone)
   {
      case DmtxOctantTop:
         locs.a = p11;
         locs.b = p01;
         break;
      case DmtxOctantLeft:
         locs.a = p01;
         locs.b = p00;
         break;
      case DmtxOctantBottom:
         locs.a = p00;
         locs.b = p10;
         break;
      case DmtxOctantRight:
         locs.a = p10;
         locs.b = p11;
         break;
      case DmtxOctantTopLeft:
      case DmtxOctantBottomRight:
         locs.a = p00;
         locs.b = p11;
         break;
      case DmtxOctantBottomLeft:
      case DmtxOctantTopRight:
      default: /* XXX this feels wrong */
         locs.a = p10;
         locs.b = p01;
         break;
   }

   return locs;
}

/**
 *
 *
 */
DmtxPassFail
dmtxDecode2SetImage(DmtxDecode2 *dec, DmtxImage *img)
{
   if(dec == NULL)
      return DmtxFail;

   dec->image = img;

   /* XXX decide here how big and how small to scale the image, and what level to go to */
   /*     store it in the decode struct */

   /* Free existing buffers if sized incorrectly */
   /* if(buffers are allocated but sized incorrectly) */
   RETURN_FAIL_IF(decode2ReleaseCacheMemory(dec) == DmtxFail);

   /* Allocate new buffers if necessary */
   /* if(buffers are not allocated) */
   dec->sobel = SobelCreate(dec->image);
   RETURN_FAIL_IF(dec->sobel == NULL);

   dec->accel = AccelCreate(dec->sobel);
   RETURN_FAIL_IF(dec->accel == NULL);

   dec->hough = HoughCreate(1,1);
   RETURN_FAIL_IF(dec->hough == NULL);

   /* Necessary to zero out buffers? */

   RETURN_FAIL_IF(SobelPopulate(dec) == DmtxFail);
   RETURN_FAIL_IF(AccelPopulate(dec) == DmtxFail);
   RETURN_FAIL_IF(HoughPopulate(dec) == DmtxFail);

   return DmtxPass;
}

#undef RETURN_FAIL_IF

/**
 *
 *
 */
DmtxPassFail
decode2ReleaseCacheMemory(DmtxDecode2 *dec)
{
   if(dec == NULL)
      return DmtxFail;

   HoughDestroy(&(dec->hough));
   AccelDestroy(&(dec->accel));
   SobelDestroy(&(dec->sobel));

   return DmtxPass;
}