libdmtx 0.7.8.7
libdmtx is a software library that enables programs to read and write Data Matrix barcodes of the modern ECC200 variety.
Loading...
Searching...
No Matches
dmtxencode.c
Go to the documentation of this file.
1
17#include <assert.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22#include "dmtx.h"
23#include "dmtxstatic.h"
24
25#undef ISDIGIT
26#define ISDIGIT(n) (n > 47 && n < 58)
27
33{
34 DmtxEncode *enc;
35
36 enc = (DmtxEncode *)calloc(1, sizeof(DmtxEncode));
37 if (enc == NULL) {
38 return NULL;
39 }
40
41 enc->scheme = DmtxSchemeAscii;
42 enc->sizeIdxRequest = DmtxSymbolSquareAuto;
43 enc->marginSize = 10;
44 enc->moduleSize = 5;
45 enc->pixelPacking = DmtxPack24bppRGB;
46 enc->imageFlip = DmtxFlipNone;
47 enc->rowPadBytes = 0;
48
49 enc->fnc1 = DmtxUndefined;
50
51 /* Initialize background color to white */
52 /* enc.region.gradient.ray.p.R = 255.0;
53 enc.region.gradient.ray.p.G = 255.0;
54 enc.region.gradient.ray.p.B = 255.0; */
55
56 /* Initialize foreground color to black */
57 /* enc.region.gradient.tMin = 0.0;
58 enc.region.gradient.tMax = xyz; */
59
60 dmtxMatrix3Identity(enc->xfrm);
61
62 return enc;
63}
64
71{
72 if (enc == NULL || *enc == NULL) {
73 return DmtxFail;
74 }
75
76 /* Free pixel array allocated in dmtxEncodeDataMatrix() */
77 if ((*enc)->image != NULL && (*enc)->image->pxl != NULL) {
78 free((*enc)->image->pxl);
79 (*enc)->image->pxl = NULL;
80 }
81
82 dmtxImageDestroy(&((*enc)->image));
83 dmtxMessageDestroy(&((*enc)->message));
84
85 free(*enc);
86
87 *enc = NULL;
88
89 return DmtxPass;
90}
91
99extern DmtxPassFail dmtxEncodeSetProp(DmtxEncode *enc, int prop, int value)
100{
101 switch (prop) {
102 /* Encoding details */
103 case DmtxPropScheme:
104 enc->scheme = value;
105 break;
107 if (value == DmtxSymbolShapeAuto) {
108 return DmtxFail;
109 }
110 enc->sizeIdxRequest = value;
111 break;
112 case DmtxPropFnc1:
113 enc->fnc1 = value;
114 break;
115
116 /* Presentation details */
118 enc->marginSize = value;
119 break;
121 enc->moduleSize = value;
122 break;
123
124 /* Image properties */
126 enc->pixelPacking = value;
127 break;
129 enc->imageFlip = value;
130 break;
132 enc->rowPadBytes = value;
133 default:
134 break;
135 }
136
137 return DmtxPass;
138}
139
146extern int dmtxEncodeGetProp(DmtxEncode *enc, int prop)
147{
148 switch (prop) {
150 return enc->marginSize;
152 return enc->moduleSize;
153 case DmtxPropScheme:
154 return enc->scheme;
155 case DmtxPropFnc1:
156 return enc->fnc1;
157 default:
158 break;
159 }
160
161 return DmtxUndefined;
162}
163
171extern DmtxPassFail dmtxEncodeDataMatrix(DmtxEncode *enc, int inputSize, unsigned char *inputString)
172{
173 int sizeIdx;
174 int width, height, bitsPerPixel;
175 unsigned char *pxl;
176 DmtxByte outputStorage[4096];
177 DmtxByteList output = dmtxByteListBuild(outputStorage, sizeof(outputStorage));
178 DmtxByteList input = dmtxByteListBuild(inputString, inputSize);
179
180 input.length = inputSize;
181
182 /* Future: stream = streamInit() ... */
183 /* Future: encodeDataCodewords(&stream) ... */
184
185 /* Encode input string into data codewords */
186 sizeIdx = encodeDataCodewords(&input, &output, enc->sizeIdxRequest, enc->scheme, enc->fnc1);
187 if (sizeIdx == DmtxUndefined || output.length <= 0) {
188 return DmtxFail;
189 }
190
191 /* encodeDataCodewords() should have updated any auto sizeIdx to a real one */
192 DmtxAssert(sizeIdx != DmtxSymbolSquareAuto && sizeIdx != DmtxSymbolRectAuto);
193
194 /* XXX we can remove a lot of this redundant data */
195 enc->region.sizeIdx = sizeIdx;
196 enc->region.symbolRows = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, sizeIdx);
197 enc->region.symbolCols = dmtxGetSymbolAttribute(DmtxSymAttribSymbolCols, sizeIdx);
198 enc->region.mappingRows = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixRows, sizeIdx);
199 enc->region.mappingCols = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixCols, sizeIdx);
200
201 /* Allocate memory for message and array */
202 enc->message = dmtxMessageCreate(sizeIdx, DmtxFormatMatrix);
203 enc->message->padCount = 0; /* XXX this needs to be added back */
204 memcpy(enc->message->code, output.b, output.length);
205
206 /* Generate error correction codewords */
207 rsEncode(enc->message, enc->region.sizeIdx);
208
209 /* Module placement in region */
210 modulePlacementEcc200(enc->message->array, enc->message->code, enc->region.sizeIdx, DmtxModuleOnRGB);
211
212 width = 2 * enc->marginSize + (enc->region.symbolCols * enc->moduleSize);
213 height = 2 * enc->marginSize + (enc->region.symbolRows * enc->moduleSize);
214 bitsPerPixel = getBitsPerPixel(enc->pixelPacking);
215 if (bitsPerPixel == DmtxUndefined) {
216 return DmtxFail;
217 }
218 DmtxAssert(bitsPerPixel % 8 == 0);
219
220 /* Allocate memory for the image to be generated */
221 pxl = (unsigned char *)malloc((width * bitsPerPixel / 8 + enc->rowPadBytes) * height);
222 if (pxl == NULL) {
223 perror("pixel malloc error");
224 return DmtxFail;
225 }
226
227 enc->image = dmtxImageCreate(pxl, width, height, enc->pixelPacking);
228 if (enc->image == NULL) {
229 perror("image malloc error");
230 return DmtxFail;
231 }
232
233 dmtxImageSetProp(enc->image, DmtxPropImageFlip, enc->imageFlip);
234 dmtxImageSetProp(enc->image, DmtxPropRowPadBytes, enc->rowPadBytes);
235
236 /* Insert finder and aligment pattern modules */
237 printPattern(enc);
238
239 return DmtxPass;
240}
241
259extern DmtxPassFail dmtxEncodeDataMosaic(DmtxEncode *enc, int inputSize, unsigned char *inputString)
260{
261 unsigned char *inputStringR, *inputStringG, *inputStringB;
262 int tmpInputSize;
263 int inputSizeR, inputSizeG, inputSizeB;
264 int sizeIdxAttempt, sizeIdxFirst, sizeIdxLast;
265 int row, col, mappingRows, mappingCols;
266 DmtxEncode *encR, *encG, *encB;
267
268 /* Use 1/3 (ceiling) of inputSize establish input size target */
269 tmpInputSize = (inputSize + 2) / 3;
270 inputSizeR = tmpInputSize;
271 inputSizeG = tmpInputSize;
272 inputSizeB = inputSize - (inputSizeR + inputSizeG);
273
274 inputStringR = inputString;
275 inputStringG = inputStringR + inputSizeR;
276 inputStringB = inputStringG + inputSizeG;
277
278 /* Use 1/3 (floor) of dataWordCount establish first symbol size attempt */
279 sizeIdxFirst = findSymbolSize(tmpInputSize, enc->sizeIdxRequest);
280 if (sizeIdxFirst == DmtxUndefined) {
281 return DmtxFail;
282 }
283
284 /* Set the last possible symbol size for this symbol shape or specific size request */
285 if (enc->sizeIdxRequest == DmtxSymbolSquareAuto) {
286 sizeIdxLast = DmtxSymbolSquareCount - 1;
287 } else if (enc->sizeIdxRequest == DmtxSymbolRectAuto) {
288 sizeIdxLast = DmtxSymbolSquareCount + DmtxSymbolRectCount - 1;
289 } else {
290 sizeIdxLast = sizeIdxFirst;
291 }
292
293 encR = encG = encB = NULL;
294
295 /* Try increasing symbol sizes until 3 of them can hold all input values */
296 for (sizeIdxAttempt = sizeIdxFirst; sizeIdxAttempt <= sizeIdxLast; sizeIdxAttempt++) {
297 dmtxEncodeDestroy(&encR);
298 dmtxEncodeDestroy(&encG);
299 dmtxEncodeDestroy(&encB);
300
301 encR = dmtxEncodeCreate();
302 encG = dmtxEncodeCreate();
303 encB = dmtxEncodeCreate();
304
305 /* Copy all settings from master DmtxEncode, including pointer to image
306 and message, which is initially null */
307 *encR = *encG = *encB = *enc;
308
309 dmtxEncodeSetProp(encR, DmtxPropSizeRequest, sizeIdxAttempt);
310 dmtxEncodeSetProp(encG, DmtxPropSizeRequest, sizeIdxAttempt);
311 dmtxEncodeSetProp(encB, DmtxPropSizeRequest, sizeIdxAttempt);
312
313 /* RED LAYER - Holds temporary copy */
314 dmtxEncodeDataMatrix(encR, inputSizeR, inputStringR);
315 if (encR->region.sizeIdx != sizeIdxAttempt) {
316 continue;
317 }
318
319 /* GREEN LAYER - Holds temporary copy */
320 dmtxEncodeDataMatrix(encG, inputSizeG, inputStringG);
321 if (encG->region.sizeIdx != sizeIdxAttempt) {
322 continue;
323 }
324
325 /* BLUE LAYER - Holds temporary copy */
326 dmtxEncodeDataMatrix(encB, inputSizeB, inputStringB);
327 if (encB->region.sizeIdx != sizeIdxAttempt) {
328 continue;
329 }
330
331 /* If we get this far we found a fit */
332 break;
333 }
334
335 if (encR == NULL || encG == NULL || encB == NULL) {
336 dmtxEncodeDestroy(&encR);
337 dmtxEncodeDestroy(&encG);
338 dmtxEncodeDestroy(&encB);
339 return DmtxFail;
340 }
341
342 /* Now we have the correct sizeIdxAttempt, and they all fit into the desired size */
343
344 /* Perform the red portion of the final encode to set internals correctly */
345 dmtxEncodeSetProp(enc, DmtxPropSizeRequest, sizeIdxAttempt);
346 dmtxEncodeDataMatrix(enc, inputSizeR, inputStringR);
347
348 /* Zero out the array and overwrite the bits in 3 passes */
349 mappingRows = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixRows, sizeIdxAttempt);
350 mappingCols = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixCols, sizeIdxAttempt);
351 memset(enc->message->array, 0x00, sizeof(unsigned char) * enc->region.mappingRows * enc->region.mappingCols);
352
353 modulePlacementEcc200(enc->message->array, encR->message->code, sizeIdxAttempt, DmtxModuleOnRed);
354
355 /* Reset DmtxModuleAssigned and DMX_MODULE_VISITED bits */
356 for (row = 0; row < mappingRows; row++) {
357 for (col = 0; col < mappingCols; col++) {
358 enc->message->array[row * mappingCols + col] &= (0xff ^ (DmtxModuleAssigned | DmtxModuleVisited));
359 }
360 }
361
362 modulePlacementEcc200(enc->message->array, encG->message->code, sizeIdxAttempt, DmtxModuleOnGreen);
363
364 /* Reset DmtxModuleAssigned and DMX_MODULE_VISITED bits */
365 for (row = 0; row < mappingRows; row++) {
366 for (col = 0; col < mappingCols; col++) {
367 enc->message->array[row * mappingCols + col] &= (0xff ^ (DmtxModuleAssigned | DmtxModuleVisited));
368 }
369 }
370
371 modulePlacementEcc200(enc->message->array, encB->message->code, sizeIdxAttempt, DmtxModuleOnBlue);
372
373 /* Destroy encR, encG, and encB */
374 dmtxEncodeDestroy(&encR);
375 dmtxEncodeDestroy(&encG);
376 dmtxEncodeDestroy(&encB);
377
378 printPattern(enc);
379
380 return DmtxPass;
381}
382
390static int encodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme,
391 int fnc1)
392{
393 int sizeIdx;
394
395 /* Encode input string into data codewords */
396 switch (scheme) {
398 sizeIdx = encodeOptimizeBest(input, output, sizeIdxRequest, fnc1);
399 break;
401 sizeIdx = DmtxUndefined; /* EncodeAutoFast(input, output, sizeIdxRequest, passFail); */
402 break;
403 default:
404 sizeIdx = encodeSingleScheme(input, output, sizeIdxRequest, scheme, fnc1);
405 break;
406 }
407
408 return sizeIdx;
409}
410
415static void printPattern(DmtxEncode *enc)
416{
417 int i, j;
418 int symbolRow, symbolCol;
419 int pixelRow, pixelCol;
420 int moduleStatus;
421 size_t rowSize, height;
422 int rgb[3];
423 double sxy, txy;
424 DmtxMatrix3 m1, m2;
425 DmtxVector2 vIn, vOut;
426
427 txy = enc->marginSize;
428 sxy = 1.0 / enc->moduleSize;
429
430 dmtxMatrix3Translate(m1, -txy, -txy);
431 dmtxMatrix3Scale(m2, sxy, -sxy);
432 dmtxMatrix3Multiply(enc->xfrm, m1, m2);
433
434 dmtxMatrix3Translate(m1, txy, txy);
435 dmtxMatrix3Scale(m2, enc->moduleSize, enc->moduleSize);
436 dmtxMatrix3Multiply(enc->rxfrm, m2, m1);
437
438 rowSize = dmtxImageGetProp(enc->image, DmtxPropRowSizeBytes);
439 height = dmtxImageGetProp(enc->image, DmtxPropHeight);
440
441 memset(enc->image->pxl, 0xff, rowSize * height);
442
443 for (symbolRow = 0; symbolRow < enc->region.symbolRows; symbolRow++) {
444 for (symbolCol = 0; symbolCol < enc->region.symbolCols; symbolCol++) {
445 vIn.x = symbolCol;
446 vIn.y = symbolRow;
447
448 dmtxMatrix3VMultiply(&vOut, &vIn, enc->rxfrm);
449
450 pixelCol = (int)(vOut.x);
451 pixelRow = (int)(vOut.y);
452
453 moduleStatus = dmtxSymbolModuleStatus(enc->message, enc->region.sizeIdx, symbolRow, symbolCol);
454
455 if (enc->image->bytesPerPixel == 1) {
456 for (i = pixelRow; i < pixelRow + enc->moduleSize; i++) {
457 for (j = pixelCol; j < pixelCol + enc->moduleSize; j++) {
458 rgb[0] = ((moduleStatus & DmtxModuleOnRed) != 0x00) ? 0 : 255;
459 dmtxImageSetPixelValue(enc->image, j, i, 0, rgb[0]);
460 }
461 }
462 } else {
463 for (i = pixelRow; i < pixelRow + enc->moduleSize; i++) {
464 for (j = pixelCol; j < pixelCol + enc->moduleSize; j++) {
465 rgb[0] = ((moduleStatus & DmtxModuleOnRed) != 0x00) ? 0 : 255;
466 rgb[1] = ((moduleStatus & DmtxModuleOnGreen) != 0x00) ? 0 : 255;
467 rgb[2] = ((moduleStatus & DmtxModuleOnBlue) != 0x00) ? 0 : 255;
468 /* dmtxImageSetRgb(enc->image, j, i, rgb); */
469 dmtxImageSetPixelValue(enc->image, j, i, 0, rgb[0]);
470 dmtxImageSetPixelValue(enc->image, j, i, 1, rgb[1]);
471 dmtxImageSetPixelValue(enc->image, j, i, 2, rgb[2]);
472 }
473 }
474 }
475 }
476 }
477}
libdmtx - Data Matrix Encoding/Decoding Library Copyright 2008, 2009 Mike Laughton.
DmtxPassFail dmtxMatrix3VMultiply(OUT DmtxVector2 *vOut, DmtxVector2 *vIn, DmtxMatrix3 m)
将向量与矩阵相乘
#define DmtxPassFail
Definition dmtx.h:42
@ DmtxPropRowSizeBytes
每一行(包括填充)在内存中的总字节数
Definition dmtx.h:202
@ DmtxPropImageFlip
图像是否需要翻转,通常用于处理上下颠倒的图像 DmtxFlip
Definition dmtx.h:203
@ DmtxPropScheme
Definition dmtx.h:181
@ DmtxPropPixelPacking
图像格式类型,像素打包方式 DmtxPackOrder
Definition dmtx.h:198
@ DmtxPropRowPadBytes
每行像素在内存中的填充或对齐字节数
Definition dmtx.h:201
@ DmtxPropMarginSize
Definition dmtx.h:183
@ DmtxPropHeight
图像高度
Definition dmtx.h:197
@ DmtxPropModuleSize
Definition dmtx.h:184
@ DmtxPropFnc1
Definition dmtx.h:185
@ DmtxPropSizeRequest
Definition dmtx.h:182
int dmtxGetSymbolAttribute(int attribute, int sizeIdx)
根据规格索引返回二维码规格各个参数
Definition dmtxsymbol.c:45
#define DmtxModuleOnRed
Definition dmtx.h:57
#define DmtxModuleAssigned
已分配
Definition dmtx.h:63
int dmtxSymbolModuleStatus(DmtxMessage *message, int sizeIdx, int symbolRow, int symbolCol)
receives symbol row and col and returns status DmtxModuleOn / !DmtxModuleOn (DmtxModuleOff) DmtxModul...
DmtxPassFail dmtxMessageDestroy(DmtxMessage **msg)
Free memory previously allocated for message.
Definition dmtxmessage.c:87
DmtxPassFail dmtxImageSetProp(DmtxImage *img, int prop, int value)
设置图像属性
Definition dmtximage.c:203
double DmtxMatrix3[3][3]
DmtxMatrix3 类型定义,表示一个3x3的双精度浮点数矩阵
Definition dmtx.h:262
void dmtxMatrix3Multiply(OUT DmtxMatrix3 mOut, DmtxMatrix3 m0, DmtxMatrix3 m1)
矩阵相乘
DmtxByteList dmtxByteListBuild(DmtxByte *storage, int capacity)
@ DmtxPack24bppRGB
Definition dmtx.h:231
@ DmtxSymAttribSymbolRows
二维码码元总行数(包括L形框和点线)
Definition dmtx.h:154
@ DmtxSymAttribSymbolCols
二维码码元总列数(包括L形框和点线)
Definition dmtx.h:155
@ DmtxSymAttribMappingMatrixRows
二维码数据区码元总行数(不包括L形框和点线)
Definition dmtx.h:160
@ DmtxSymAttribMappingMatrixCols
二维码数据区码元总列数(不包括L形框和点线)
Definition dmtx.h:161
@ DmtxFlipNone
Definition dmtx.h:244
#define DmtxPass
Definition dmtx.h:43
#define DmtxFormatMatrix
Definition dmtx.h:50
enum DmtxScheme_enum DmtxScheme
#define DmtxModuleOnBlue
Definition dmtx.h:59
DmtxPassFail dmtxImageDestroy(DmtxImage **img)
Free libdmtx image memory.
Definition dmtximage.c:167
#define DmtxUndefined
Definition dmtx.h:40
#define DmtxModuleOnRGB
OnRed | OnGreen | OnBlue.
Definition dmtx.h:60
@ DmtxSchemeAutoBest
Definition dmtx.h:89
@ DmtxSchemeAutoFast
Definition dmtx.h:88
@ DmtxSchemeAscii
Definition dmtx.h:90
void dmtxMatrix3Translate(OUT DmtxMatrix3 m, double tx, double ty)
生成平移变换矩阵
Definition dmtxmatrix3.c:82
DmtxMessage * dmtxMessageCreate(int sizeIdx, int symbolFormat)
Allocate memory for message.
Definition dmtxmessage.c:30
DmtxImage * dmtxImageCreate(unsigned char *pxl, int width, int height, int pack)
libdmtx stores image data as a large one-dimensional array of packed pixels, reading from the array w...
Definition dmtximage.c:78
#define DmtxSymbolRectCount
长方形二维码种类个数
Definition dmtx.h:54
#define DmtxModuleVisited
已访问
Definition dmtx.h:64
void dmtxMatrix3Identity(OUT DmtxMatrix3 m)
生成单位变换矩阵
Definition dmtxmatrix3.c:56
int dmtxImageGetProp(DmtxImage *img, int prop)
获取图像属性
Definition dmtximage.c:228
unsigned char DmtxByte
Definition dmtx.h:293
#define DmtxSymbolSquareCount
正方形二维码种类个数
Definition dmtx.h:53
#define DmtxFail
Definition dmtx.h:44
DmtxPassFail dmtxImageSetPixelValue(DmtxImage *img, int x, int y, int channel, int value)
设置指定坐标、通道的像素值
Definition dmtximage.c:337
#define DmtxModuleOnGreen
绿
Definition dmtx.h:58
void dmtxMatrix3Scale(OUT DmtxMatrix3 m, double sx, double sy)
生成缩放变换矩阵
@ DmtxSymbolRectAuto
Definition dmtx.h:100
@ DmtxSymbolShapeAuto
Definition dmtx.h:102
@ DmtxSymbolSquareAuto
Definition dmtx.h:101
DmtxEncode * dmtxEncodeCreate(void)
Initialize encode struct with default values.
Definition dmtxencode.c:32
DmtxPassFail dmtxEncodeSetProp(DmtxEncode *enc, int prop, int value)
Set encoding behavior property.
Definition dmtxencode.c:99
DmtxPassFail dmtxEncodeDataMosaic(DmtxEncode *enc, int inputSize, unsigned char *inputString)
Convert message into Data Mosaic image.
Definition dmtxencode.c:259
static void printPattern(DmtxEncode *enc)
Write encoded message to image.
Definition dmtxencode.c:415
DmtxPassFail dmtxEncodeDestroy(DmtxEncode **enc)
Deinitialize encode struct.
Definition dmtxencode.c:70
static int encodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1)
Convert input into message using specific encodation scheme.
Definition dmtxencode.c:390
int dmtxEncodeGetProp(DmtxEncode *enc, int prop)
Get encoding behavior property.
Definition dmtxencode.c:146
DmtxPassFail dmtxEncodeDataMatrix(DmtxEncode *enc, int inputSize, unsigned char *inputString)
Convert message into Data Matrix image.
Definition dmtxencode.c:171
static int modulePlacementEcc200(INOUT unsigned char *modules, OUT unsigned char *codewords, int sizeIdx, int moduleOnColor)
通过DataMatrix数据区的二进制矩阵,根据DataMatrix的排列规则,得到码字(codewords)
static DmtxPassFail rsEncode(DmtxMessage *message, int sizeIdx)
Encode xyz.
Definition dmtxreedsol.c:83
libdmtx - Data Matrix Encoding/Decoding Library Copyright 2008, 2009 Mike Laughton.
static int encodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1)
static int encodeOptimizeBest(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, int fnc1)
static int getBitsPerPixel(int pack)
#define DmtxAssert(expr)
Definition dmtxstatic.h:96
static int findSymbolSize(int dataWords, int sizeIdxRequest)
DmtxByteList Use signed int for length fields instead of size_t to play nicely with RS arithmetic.
DmtxEncode.
二维向量
Definition dmtx.h:277