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
dmtxencodebase256.c
Go to the documentation of this file.
1
17#include <assert.h>
18
19#include "dmtx.h"
20#include "dmtxstatic.h"
21
27{
28 DmtxByte value;
29
30 if (streamInputHasNext(stream)) {
31 /* Check for FNC1 character, which needs to be sent in ASCII */
32 value = streamInputPeekNext(stream);
33 CHKERR;
34 if (stream->fnc1 != DmtxUndefined && (int)value == stream->fnc1) {
36
38 CHKERR;
40 CHKERR;
41 return;
42 }
43
44 value = streamInputAdvanceNext(stream);
45 CHKERR;
46 appendValueBase256(stream, value);
47 CHKERR;
48 }
49}
50
55static void appendValueBase256(DmtxEncodeStream *stream, DmtxByte value)
56{
58
59 streamOutputChainAppend(stream, randomize255State(value, stream->output->length + 1));
60 CHKERR;
61 stream->outputChainValueCount++;
62
64 CHKERR;
65}
66
73static void completeIfDoneBase256(DmtxEncodeStream *stream, int sizeIdxRequest)
74{
75 int sizeIdx;
76 int headerByteCount, outputLength, symbolRemaining;
77
78 if (stream->status == DmtxStatusComplete) {
79 return;
80 }
81
82 if (!streamInputHasNext(stream)) {
83 headerByteCount = stream->outputChainWordCount - stream->outputChainValueCount;
84 DmtxAssert(headerByteCount == 1 || headerByteCount == 2);
85
86 /* Check for special case where every last symbol word is used */
87 if (headerByteCount == 2) {
88 /* Find symbol size as if headerByteCount was only 1 */
89 outputLength = stream->output->length - 1;
90 sizeIdx = findSymbolSize(outputLength, sizeIdxRequest); /* No CHKSIZE */
91 if (sizeIdx != DmtxUndefined) {
92 symbolRemaining = getRemainingSymbolCapacity(outputLength, sizeIdx);
93
94 if (symbolRemaining == 0) {
95 /* Perfect fit -- complete encoding */
96 updateBase256ChainHeader(stream, sizeIdx);
97 CHKERR;
98 streamMarkComplete(stream, sizeIdx);
99 return;
100 }
101 }
102 }
103
104 /* Normal case */
105 sizeIdx = findSymbolSize(stream->output->length, sizeIdxRequest);
106 CHKSIZE;
108 padRemainingInAscii(stream, sizeIdx);
109 streamMarkComplete(stream, sizeIdx);
110 }
111}
112
117static void updateBase256ChainHeader(DmtxEncodeStream *stream, int perfectSizeIdx)
118{
119 int headerIndex;
120 int outputLength;
121 int headerByteCount;
122 int symbolDataWords;
123 DmtxBoolean perfectFit;
124 DmtxByte headerValue0;
125 DmtxByte headerValue1;
126
127 outputLength = stream->outputChainValueCount;
128 headerIndex = stream->output->length - stream->outputChainWordCount;
129 headerByteCount = stream->outputChainWordCount - stream->outputChainValueCount;
130 perfectFit = (perfectSizeIdx == DmtxUndefined) ? DmtxFalse : DmtxTrue;
131
132 /*
133 * If requested perfect fit verify symbol capacity against final length
134 */
135
136 if (perfectFit) {
137 symbolDataWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, perfectSizeIdx);
138 if (symbolDataWords != stream->output->length - 1) {
140 return;
141 }
142 }
143
144 /*
145 * Adjust header to hold correct number of bytes, not worrying about the
146 * values held there until below. Note: Header bytes are not considered
147 * scheme "values" so we can insert or remove them without updating the
148 * outputChainValueCount.
149 */
150
151 if (headerByteCount == 0 && stream->outputChainWordCount == 0) {
152 /* No output words written yet -- insert single header byte */
153 streamOutputChainAppend(stream, 0);
154 CHKERR;
155 headerByteCount++;
156 } else if (!perfectFit && headerByteCount == 1 && outputLength > 249) {
157 /* Beyond 249 bytes requires a second header byte */
159 CHKERR;
160 headerByteCount++;
161 } else if (perfectFit && headerByteCount == 2) {
162 /* Encoding to exact end of symbol only requires single byte */
164 CHKERR;
165 headerByteCount--;
166 }
167
168 /*
169 * Encode header byte(s) with current length
170 */
171
172 if (!perfectFit && headerByteCount == 1 && outputLength <= 249) {
173 /* Normal condition for chain length < 250 bytes */
174 headerValue0 = randomize255State(outputLength, headerIndex + 1);
175 streamOutputSet(stream, headerIndex, headerValue0);
176 CHKERR;
177 } else if (!perfectFit && headerByteCount == 2 && outputLength > 249) {
178 /* Normal condition for chain length >= 250 bytes */
179 headerValue0 = randomize255State(outputLength / 250 + 249, headerIndex + 1);
180 streamOutputSet(stream, headerIndex, headerValue0);
181 CHKERR;
182
183 headerValue1 = randomize255State(outputLength % 250, headerIndex + 2);
184 streamOutputSet(stream, headerIndex + 1, headerValue1);
185 CHKERR;
186 } else if (perfectFit && headerByteCount == 1) {
187 /* Special condition when Base 256 stays in effect to end of symbol */
188 headerValue0 = randomize255State(0, headerIndex + 1); /* XXX replace magic value 0? */
189 streamOutputSet(stream, headerIndex, headerValue0);
190 CHKERR;
191 } else {
193 return;
194 }
195}
196
202{
203 DmtxByte value;
204 DmtxPassFail passFail;
205 int i, chainStart;
206
207 chainStart = stream->output->length - stream->outputChainWordCount;
208 dmtxByteListPush(stream->output, 0, &passFail);
209 if (passFail == DmtxPass) {
210 for (i = stream->output->length - 1; i > chainStart; i--) {
211 value = unRandomize255State(stream->output->b[i - 1], i);
212 stream->output->b[i] = randomize255State(value, i + 1);
213 }
214
215 stream->outputChainWordCount++;
216 } else {
218 }
219}
220
226{
227 DmtxByte value;
228 DmtxPassFail passFail;
229 int i, chainStart;
230
231 chainStart = stream->output->length - stream->outputChainWordCount;
232
233 for (i = chainStart; i < stream->output->length - 1; i++) {
234 value = unRandomize255State(stream->output->b[i + 1], i + 2);
235 stream->output->b[i] = randomize255State(value, i + 1);
236 }
237
238 dmtxByteListPop(stream->output, &passFail);
239 if (passFail == DmtxPass) {
240 stream->outputChainWordCount--;
241 } else {
243 }
244}
245
252static DmtxByte randomize255State(DmtxByte value, int position)
253{
254 int pseudoRandom, tmp;
255
256 pseudoRandom = ((149 * position) % 255) + 1;
257 tmp = value + pseudoRandom;
258
259 return (tmp <= 255) ? tmp : tmp - 256;
260}
261
268static unsigned char unRandomize255State(unsigned char value, int idx)
269{
270 int pseudoRandom;
271 int tmp;
272
273 pseudoRandom = ((149 * idx) % 255) + 1;
274 tmp = value - pseudoRandom;
275 if (tmp < 0) {
276 tmp += 256;
277 }
278
279 DmtxAssert(tmp >= 0 && tmp < 256);
280
281 return (unsigned char)tmp;
282}
libdmtx - Data Matrix Encoding/Decoding Library Copyright 2008, 2009 Mike Laughton.
#define DmtxPassFail
Definition dmtx.h:42
int dmtxGetSymbolAttribute(int attribute, int sizeIdx)
根据规格索引返回二维码规格各个参数
Definition dmtxsymbol.c:45
#define DmtxTrue
Definition dmtx.h:47
void dmtxByteListPush(DmtxByteList *list, DmtxByte value, DmtxPassFail *passFail)
@ DmtxSymAttribSymbolDataWords
Definition dmtx.h:165
#define DmtxBoolean
Definition dmtx.h:46
#define DmtxPass
Definition dmtx.h:43
#define DmtxUndefined
Definition dmtx.h:40
@ DmtxSchemeBase256
Definition dmtx.h:95
@ DmtxSchemeAscii
Definition dmtx.h:90
DmtxByte dmtxByteListPop(DmtxByteList *list, DmtxPassFail *passFail)
#define DmtxFalse
Definition dmtx.h:48
unsigned char DmtxByte
Definition dmtx.h:293
@ DmtxStatusComplete
Definition dmtx.h:81
static void encodeNextChunkBase256(DmtxEncodeStream *stream)
static void appendValueBase256(DmtxEncodeStream *stream, DmtxByte value)
static void updateBase256ChainHeader(DmtxEncodeStream *stream, int perfectSizeIdx)
static void base256OutputChainRemoveFirst(DmtxEncodeStream *stream)
remove first element from chain, shifting all following elements back by one used for binary length c...
static void base256OutputChainInsertFirst(DmtxEncodeStream *stream)
insert element at beginning of chain, shifting all following elements forward by one used for binary ...
static void completeIfDoneBase256(DmtxEncodeStream *stream, int sizeIdxRequest)
check remaining symbol capacity and remaining codewords if the chain can finish perfectly at the end ...
static DmtxByte randomize255State(DmtxByte value, int position)
Randomize 255 state.
static unsigned char unRandomize255State(unsigned char value, int idx)
Unrandomize 255 state.
libdmtx - Data Matrix Encoding/Decoding Library Copyright 2008, 2009 Mike Laughton.
static DmtxByte streamInputAdvanceNext(DmtxEncodeStream *stream)
#define CHKSIZE
Definition dmtxstatic.h:88
#define CHKSCHEME(s)
Definition dmtxstatic.h:71
static void streamOutputChainAppend(DmtxEncodeStream *stream, DmtxByte value)
static void streamOutputSet(DmtxEncodeStream *stream, int index, DmtxByte value)
@ DmtxErrorUnknown
Definition dmtxstatic.h:394
static void padRemainingInAscii(DmtxEncodeStream *stream, int sizeIdx)
#define DmtxAssert(expr)
Definition dmtxstatic.h:96
static DmtxByte streamInputPeekNext(DmtxEncodeStream *stream)
static int findSymbolSize(int dataWords, int sizeIdxRequest)
static void streamMarkComplete(DmtxEncodeStream *stream, int sizeIdx)
#define DmtxUnlatchImplicit
Definition dmtxstatic.h:55
static void encodeChangeScheme(DmtxEncodeStream *stream, DmtxScheme targetScheme, int unlatchType)
static int getRemainingSymbolCapacity(int outputLength, int sizeIdx)
static void appendValueAscii(DmtxEncodeStream *stream, DmtxByte value)
#define DmtxUnlatchExplicit
Definition dmtxstatic.h:54
#define DmtxValueFNC1
Definition dmtxstatic.h:42
#define CHKERR
Definition dmtxstatic.h:80
static void streamMarkFatal(DmtxEncodeStream *stream, int reasonIdx)
static DmtxBoolean streamInputHasNext(DmtxEncodeStream *stream)
DmtxByte * b
Definition dmtx.h:305
DmtxByteList * output
Definition dmtx.h:319
DmtxStatus status
Definition dmtx.h:317