internal void DecodeDataStream(DmtxSymbolSize sizeIdx, byte[] outputStart) { bool macro = false; this.Output = outputStart ?? this.Output; this._outputIdx = 0; byte[] ptr = this.Code; int dataEndIndex = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribSymbolDataWords, sizeIdx); /* Print macro header if first codeword triggers it */ if (ptr[0] == DmtxConstants.DmtxChar05Macro || ptr[0] == DmtxConstants.DmtxChar06Macro) { PushOutputMacroHeader(ptr[0]); macro = true; } for (int codeIter = 0; codeIter < dataEndIndex;) { DmtxScheme encScheme = GetEncodationScheme(this.Code[codeIter]); if (encScheme != DmtxScheme.DmtxSchemeAscii) { codeIter++; } switch (encScheme) { case DmtxScheme.DmtxSchemeAscii: codeIter = DecodeSchemeAscii(codeIter, dataEndIndex); break; case DmtxScheme.DmtxSchemeC40: case DmtxScheme.DmtxSchemeText: codeIter = DecodeSchemeC40Text(codeIter, dataEndIndex, encScheme); break; case DmtxScheme.DmtxSchemeX12: codeIter = DecodeSchemeX12(codeIter, dataEndIndex); break; case DmtxScheme.DmtxSchemeEdifact: codeIter = DecodeSchemeEdifact(codeIter, dataEndIndex); break; case DmtxScheme.DmtxSchemeBase256: codeIter = DecodeSchemeBase256(codeIter, dataEndIndex); break; } } /* Print macro trailer if required */ if (macro) { PushOutputMacroTrailer(); } }
internal DmtxEncode() { this._scheme = DmtxScheme.DmtxSchemeAscii; this._sizeIdxRequest = DmtxSymbolSize.DmtxSymbolSquareAuto; this._marginSize = 10; this._moduleSize = 5; this._pixelPacking = DmtxPackOrder.DmtxPack24bppRGB; this._imageFlip = DmtxFlip.DmtxFlipNone; this._rowPadBytes = 0; }
private DmtxEncode(DmtxEncode src) { this._scheme = src._scheme; this._sizeIdxRequest = src._sizeIdxRequest; this._marginSize = src._marginSize; this._moduleSize = src._moduleSize; this._pixelPacking = src._pixelPacking; this._imageFlip = src._imageFlip; this._rowPadBytes = src._rowPadBytes; this._image = src._image; this._message = src._message; this._method = src._method; this._region = src._region; }
int DecodeSchemeC40Text(int startIndex, int endIndex, DmtxScheme encScheme) { int[] c40Values = new int[3]; C40TextState state = new C40TextState { Shift = DmtxConstants.DmtxC40TextBasicSet, UpperShift = false }; if (!(encScheme == DmtxScheme.DmtxSchemeC40 || encScheme == DmtxScheme.DmtxSchemeText)) { throw new ArgumentException("Invalid scheme selected for decodind!"); } while (startIndex < endIndex) { /* FIXME Also check that ptr+1 is safe to access */ int packed = (this.Code[startIndex] << 8) | this.Code[startIndex + 1]; c40Values[0] = ((packed - 1) / 1600); c40Values[1] = ((packed - 1) / 40) % 40; c40Values[2] = (packed - 1) % 40; startIndex += 2; int i; for (i = 0; i < 3; i++) { if (state.Shift == DmtxConstants.DmtxC40TextBasicSet) { /* Basic set */ if (c40Values[i] <= 2) { state.Shift = c40Values[i] + 1; } else if (c40Values[i] == 3) { PushOutputC40TextWord(ref state, ' '); } else if (c40Values[i] <= 13) { PushOutputC40TextWord(ref state, c40Values[i] - 13 + '9'); /* 0-9 */ } else if (c40Values[i] <= 39) { if (encScheme == DmtxScheme.DmtxSchemeC40) { PushOutputC40TextWord(ref state, c40Values[i] - 39 + 'Z'); /* A-Z */ } else if (encScheme == DmtxScheme.DmtxSchemeText) { PushOutputC40TextWord(ref state, c40Values[i] - 39 + 'z'); /* a-z */ } } } else if (state.Shift == DmtxConstants.DmtxC40TextShift1) { /* Shift 1 set */ PushOutputC40TextWord(ref state, c40Values[i]); /* ASCII 0 - 31 */ } else if (state.Shift == DmtxConstants.DmtxC40TextShift2) { /* Shift 2 set */ if (c40Values[i] <= 14) { PushOutputC40TextWord(ref state, c40Values[i] + 33); /* ASCII 33 - 47 */ } else if (c40Values[i] <= 21) { PushOutputC40TextWord(ref state, c40Values[i] + 43); /* ASCII 58 - 64 */ } else if (c40Values[i] <= 26) { PushOutputC40TextWord(ref state, c40Values[i] + 69); /* ASCII 91 - 95 */ } else if (c40Values[i] == 27) { PushOutputC40TextWord(ref state, 0x1d); /* FNC1 -- XXX depends on position? */ } else if (c40Values[i] == 30) { state.UpperShift = true; state.Shift = DmtxConstants.DmtxC40TextBasicSet; } } else if (state.Shift == DmtxConstants.DmtxC40TextShift3) { /* Shift 3 set */ if (encScheme == DmtxScheme.DmtxSchemeC40) { PushOutputC40TextWord(ref state, c40Values[i] + 96); } else if (encScheme == DmtxScheme.DmtxSchemeText) { if (c40Values[i] == 0) { PushOutputC40TextWord(ref state, c40Values[i] + 96); } else if (c40Values[i] <= 26) { PushOutputC40TextWord(ref state, c40Values[i] - 26 + 'Z'); /* A-Z */ } else { PushOutputC40TextWord(ref state, c40Values[i] - 31 + 127); /* { | } ~ DEL */ } } } } /* Unlatch if codeword 254 follows 2 codewords in C40/Text encodation */ if (this.Code[startIndex] == DmtxConstants.DmtxCharTripletUnlatch) { return(startIndex + 1); } /* Unlatch is implied if only one codeword remains */ if (endIndex - startIndex == 1) { return(startIndex); } } return(startIndex); }
int DecodeSchemeC40Text(int startIndex, int endIndex, DmtxScheme encScheme) { int i; int packed; int[] c40Values = new int[3]; C40TextState state = new C40TextState(); state.Shift = DmtxConstants.DmtxC40TextBasicSet; state.UpperShift = false; if (!(encScheme == DmtxScheme.DmtxSchemeC40 || encScheme == DmtxScheme.DmtxSchemeText)) { throw new ArgumentException("Invalid scheme selected for decodind!"); } while (startIndex < endIndex) { /* FIXME Also check that ptr+1 is safe to access */ packed = (((int)this._code[startIndex]) << 8) | (int)this._code[startIndex + 1]; c40Values[0] = ((packed - 1) / 1600); c40Values[1] = ((packed - 1) / 40) % 40; c40Values[2] = (packed - 1) % 40; startIndex += 2; for (i = 0; i < 3; i++) { if (state.Shift == DmtxConstants.DmtxC40TextBasicSet) { /* Basic set */ if (c40Values[i] <= 2) { state.Shift = c40Values[i] + 1; } else if (c40Values[i] == 3) { PushOutputC40TextWord(ref state, ' '); } else if (c40Values[i] <= 13) { PushOutputC40TextWord(ref state, c40Values[i] - 13 + '9'); /* 0-9 */ } else if (c40Values[i] <= 39) { if (encScheme == DmtxScheme.DmtxSchemeC40) { PushOutputC40TextWord(ref state, c40Values[i] - 39 + 'Z'); /* A-Z */ } else if (encScheme == DmtxScheme.DmtxSchemeText) { PushOutputC40TextWord(ref state, c40Values[i] - 39 + 'z'); /* a-z */ } } } else if (state.Shift == DmtxConstants.DmtxC40TextShift1) { /* Shift 1 set */ PushOutputC40TextWord(ref state, c40Values[i]); /* ASCII 0 - 31 */ } else if (state.Shift == DmtxConstants.DmtxC40TextShift2) { /* Shift 2 set */ if (c40Values[i] <= 14) { PushOutputC40TextWord(ref state, c40Values[i] + 33); /* ASCII 33 - 47 */ } else if (c40Values[i] <= 21) { PushOutputC40TextWord(ref state, c40Values[i] + 43); /* ASCII 58 - 64 */ } else if (c40Values[i] <= 26) { PushOutputC40TextWord(ref state, c40Values[i] + 69); /* ASCII 91 - 95 */ } else if (c40Values[i] == 27) { PushOutputC40TextWord(ref state, 0x1d); /* FNC1 -- XXX depends on position? */ } else if (c40Values[i] == 30) { state.UpperShift = true; state.Shift = DmtxConstants.DmtxC40TextBasicSet; } } else if (state.Shift == DmtxConstants.DmtxC40TextShift3) { /* Shift 3 set */ if (encScheme == DmtxScheme.DmtxSchemeC40) { PushOutputC40TextWord(ref state, c40Values[i] + 96); } else if (encScheme == DmtxScheme.DmtxSchemeText) { if (c40Values[i] == 0) PushOutputC40TextWord(ref state, c40Values[i] + 96); else if (c40Values[i] <= 26) PushOutputC40TextWord(ref state, c40Values[i] - 26 + 'Z'); /* A-Z */ else PushOutputC40TextWord(ref state, c40Values[i] - 31 + 127); /* { | } ~ DEL */ } } } /* Unlatch if codeword 254 follows 2 codewords in C40/Text encodation */ if (_code[startIndex] == DmtxConstants.DmtxCharTripletUnlatch) return startIndex + 1; /* Unlatch is implied if only one codeword remains */ if (endIndex - startIndex == 1) return startIndex; } return startIndex; }
private int EncodeSingleScheme(byte[] buf, byte[] codewords, DmtxScheme scheme) { int size; bool err; DmtxChannel channel = new DmtxChannel(); InitChannel(channel, codewords); while (channel.InputIndex < channel.Input.Length) { err = EncodeNextWord(channel, scheme); if (!err) return 0; /* DumpChannel(&channel); */ if (channel.Invalid != DmtxChannelStatus.DmtxChannelValid) { return 0; } } /* DumpChannel(&channel); */ size = channel.EncodedLength / 12; for (int i = 0; i < size; i++) { buf[i] = channel.EncodedWords[i]; } return size; }
private bool EncodeNextWord(DmtxChannel channel, DmtxScheme targetScheme) { /* Change to new encodation scheme if necessary */ if (channel.EncScheme != targetScheme) { ChangeEncScheme(channel, targetScheme, DmtxUnlatch.Explicit); if (channel.Invalid != DmtxChannelStatus.DmtxChannelValid) return false; } if (channel.EncScheme != targetScheme) { throw new Exception("For encoding, channel scheme must equal target scheme!"); } /* Encode next input value */ switch (channel.EncScheme) { case DmtxScheme.DmtxSchemeAscii: return EncodeAsciiCodeword(channel); case DmtxScheme.DmtxSchemeC40: return EncodeTripletCodeword(channel); case DmtxScheme.DmtxSchemeText: return EncodeTripletCodeword(channel); case DmtxScheme.DmtxSchemeX12: return EncodeTripletCodeword(channel); case DmtxScheme.DmtxSchemeEdifact: return EncodeEdifactCodeword(channel); case DmtxScheme.DmtxSchemeBase256: return EncodeBase256Codeword(channel); default: return false; } }
private void ChangeEncScheme(DmtxChannel channel, DmtxScheme targetScheme, DmtxUnlatch unlatchType) { int advance; if (channel.EncScheme == targetScheme) { throw new Exception("Target scheme already equals channel scheme, cannot be changed!"); } /* Unlatch to ASCII (base encodation scheme) */ switch (channel.EncScheme) { case DmtxScheme.DmtxSchemeAscii: /* Nothing to do */ if (channel.CurrentLength % 12 != 0) { throw new Exception("Invalid current length detected encoding ascii code"); } break; case DmtxScheme.DmtxSchemeC40: case DmtxScheme.DmtxSchemeText: case DmtxScheme.DmtxSchemeX12: /* Can't unlatch unless currently at a byte boundary */ if ((channel.CurrentLength % 12) != 0) { channel.Invalid = DmtxChannelStatus.DmtxChannelCannotUnlatch; return; } /* Can't unlatch if last word in previous triplet is a shift */ if (channel.CurrentLength != channel.EncodedLength) { channel.Invalid = DmtxChannelStatus.DmtxChannelCannotUnlatch; return; } /* Unlatch to ASCII and increment progress */ if (unlatchType == DmtxUnlatch.Explicit) { PushInputWord(channel, (byte)DmtxConstants.DmtxCharTripletUnlatch); IncrementProgress(channel, 12); } break; case DmtxScheme.DmtxSchemeEdifact: /* must overwrite next 6 bits (after current) with 011111 (31) and then fill remaining bits until next byte bounday with zeros then set encodedLength, encodedTwothirdsbits, currentLength, currentTwothirdsbits. PushInputWord guarantees that remaining bits are padded to 0, so just push the unlatch code and then increment current and encoded length */ if (channel.CurrentLength % 3 != 0) { throw new Exception("Error changing encryption scheme, current length is invalid!"); } if (unlatchType == DmtxUnlatch.Explicit) { PushInputWord(channel, (byte)DmtxConstants.DmtxCharEdifactUnlatch); IncrementProgress(channel, 9); } /* Advance progress to next byte boundary */ advance = (channel.CurrentLength % 4) * 3; channel.CurrentLength += advance; channel.EncodedLength += advance; /* assert(remaining bits are zero); */ break; case DmtxScheme.DmtxSchemeBase256: /* since Base 256 stores the length value at the beginning of the string instead of using an unlatch character, "unlatching" Base 256 involves going to the beginning of this stretch of Base 256 codewords and update the placeholder with the current length. Note that the Base 256 length value can either be 1 or 2 bytes, depending on the length of the current stretch of Base 256 chars. However, this value will already have the correct number of codewords allocated since this is checked every time a new Base 256 codeword is pushed to the channel. */ break; default: break; } channel.EncScheme = DmtxScheme.DmtxSchemeAscii; /* Latch to new encodation scheme */ switch (targetScheme) { case DmtxScheme.DmtxSchemeAscii: /* Nothing to do */ break; case DmtxScheme.DmtxSchemeC40: PushInputWord(channel, (byte)DmtxConstants.DmtxCharC40Latch); IncrementProgress(channel, 12); break; case DmtxScheme.DmtxSchemeText: PushInputWord(channel, (byte)DmtxConstants.DmtxCharTextLatch); IncrementProgress(channel, 12); break; case DmtxScheme.DmtxSchemeX12: PushInputWord(channel, (byte)DmtxConstants.DmtxCharX12Latch); IncrementProgress(channel, 12); break; case DmtxScheme.DmtxSchemeEdifact: PushInputWord(channel, (byte)DmtxConstants.DmtxCharEdifactLatch); IncrementProgress(channel, 12); break; case DmtxScheme.DmtxSchemeBase256: PushInputWord(channel, (byte)DmtxConstants.DmtxCharBase256Latch); IncrementProgress(channel, 12); /* Write temporary field length (0 indicates remainder of symbol) */ PushInputWord(channel, Randomize255State(0, 2)); IncrementProgress(channel, 12); break; default: break; } channel.EncScheme = targetScheme; channel.FirstCodeWord = channel.CurrentLength - 12; if (channel.FirstCodeWord % 12 != 0) { throw new Exception("Error while changin encoding scheme, invalid first code word!"); } }
private int GetC40TextX12Words(int[] outputWords, byte inputWord, DmtxScheme encScheme) { int count; if (encScheme != DmtxScheme.DmtxSchemeX12 && encScheme != DmtxScheme.DmtxSchemeText && encScheme != DmtxScheme.DmtxSchemeC40) { throw new Exception("Invalid encoding scheme selected!"); } count = 0; /* Handle extended ASCII with Upper Shift character */ if (inputWord > 127) { if (encScheme == DmtxScheme.DmtxSchemeX12) { return 0; } else { outputWords[count++] = DmtxConstants.DmtxCharTripletShift2; outputWords[count++] = 30; inputWord -= 128; } } /* Handle all other characters according to encodation scheme */ if (encScheme == DmtxScheme.DmtxSchemeX12) { if (inputWord == 13) outputWords[count++] = 0; else if (inputWord == 42) outputWords[count++] = 1; else if (inputWord == 62) outputWords[count++] = 2; else if (inputWord == 32) outputWords[count++] = 3; else if (inputWord >= 48 && inputWord <= 57) outputWords[count++] = inputWord - 44; else if (inputWord >= 65 && inputWord <= 90) outputWords[count++] = inputWord - 51; } else { /* encScheme is C40 or Text */ if (inputWord <= 31) { outputWords[count++] = DmtxConstants.DmtxCharTripletShift1; outputWords[count++] = inputWord; } else if (inputWord == 32) { outputWords[count++] = 3; } else if (inputWord <= 47) { outputWords[count++] = DmtxConstants.DmtxCharTripletShift2; outputWords[count++] = inputWord - 33; } else if (inputWord <= 57) { outputWords[count++] = inputWord - 44; } else if (inputWord <= 64) { outputWords[count++] = DmtxConstants.DmtxCharTripletShift2; outputWords[count++] = inputWord - 43; } else if (inputWord <= 90 && encScheme == DmtxScheme.DmtxSchemeC40) { outputWords[count++] = inputWord - 51; } else if (inputWord <= 90 && encScheme == DmtxScheme.DmtxSchemeText) { outputWords[count++] = DmtxConstants.DmtxCharTripletShift3; outputWords[count++] = inputWord - 64; } else if (inputWord <= 95) { outputWords[count++] = DmtxConstants.DmtxCharTripletShift2; outputWords[count++] = inputWord - 69; } else if (inputWord == 96 && encScheme == DmtxScheme.DmtxSchemeText) { outputWords[count++] = DmtxConstants.DmtxCharTripletShift3; outputWords[count++] = 0; } else if (inputWord <= 122 && encScheme == DmtxScheme.DmtxSchemeText) { outputWords[count++] = inputWord - 83; } else if (inputWord <= 127) { outputWords[count++] = DmtxConstants.DmtxCharTripletShift3; outputWords[count++] = inputWord - 96; } } return count; }
private DmtxChannel FindBestChannel(DmtxChannelGroup group, DmtxScheme targetScheme) { bool err; DmtxChannel channel; DmtxChannel winner = null; for (DmtxScheme encFrom = DmtxScheme.DmtxSchemeAscii; encFrom <= DmtxScheme.DmtxSchemeBase256; encFrom++) { channel = group.Channels[(int)encFrom]; /* If from channel doesn't hold valid data because it couldn't represent the previous value then skip it */ if (channel.Invalid != DmtxChannelStatus.DmtxChannelValid) { continue; } /* If channel has already processed all of its input values then it cannot be used as a starting point */ if (channel.InputIndex == channel.Input.Length) continue; err = EncodeNextWord(channel, targetScheme); if (err == false) { /* XXX fix this */ } /* If channel scheme can't represent next word then stop for this channel */ if ((channel.Invalid & DmtxChannelStatus.DmtxChannelUnsupportedChar) != 0) { winner = channel; break; } /* If channel scheme was unable to unlatch here then skip */ if ((channel.Invalid & DmtxChannelStatus.DmtxChannelCannotUnlatch) != 0) { continue; } if (winner == null || channel.CurrentLength < winner.CurrentLength) { winner = channel; } } return winner; }