⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dmtxencode.c

📁 Datamatrix二维码库和测试程序,运行于linux,仔细研究可以很容易转化成VC程序,有这就没必要化钱买个控件了,本人libdmtx-0.3版本转化过,的确可行,现在把找到该版本的libdmtx
💻 C
📖 第 1 页 / 共 4 页
字号:
 * @param  codewordPosition * @return Randomized value */static unsigned charRandomize255State(unsigned char codewordValue, int codewordPosition){   int pseudoRandom;   int tmp;   pseudoRandom = ((149 * codewordPosition) % 255) + 1;   tmp = codewordValue + pseudoRandom;   return (tmp <= 255) ? tmp : tmp - 256;}/** * @brief  Write encoded message to image * @param  enc * @return void */static voidPrintPattern(DmtxEncode *enc){   int i, j;   int symbolRow, symbolCol;   int pixelRow, pixelCol;   int moduleStatus;   double sxy, txy;   DmtxRgb rgb;   DmtxMatrix3 m1, m2;   DmtxVector2 vIn, vOut;   txy = enc->marginSize;   sxy = 1.0/enc->moduleSize;   dmtxMatrix3Translate(m1, -txy, -txy);   dmtxMatrix3Scale(m2, sxy, -sxy);   dmtxMatrix3Multiply(enc->xfrm, m1, m2);   dmtxMatrix3Translate(m1, txy, txy);   dmtxMatrix3Scale(m2, enc->moduleSize, enc->moduleSize);   dmtxMatrix3Multiply(enc->rxfrm, m2, m1);   /* Print raster version of barcode pattern      IMPORTANT: DmtxImage is stored with its origin at bottom-right      (unlike common image file formats) to preserve "right-handed" 2D space */   memset(enc->image->pxl, 0xff, dmtxImageGetProp(enc->image, DmtxPropArea) * sizeof(DmtxRgb));   for(symbolRow = 0; symbolRow < enc->region.symbolRows; symbolRow++) {      for(symbolCol = 0; symbolCol < enc->region.symbolCols; symbolCol++) {         vIn.X = symbolCol;         vIn.Y = symbolRow;         dmtxMatrix3VMultiply(&vOut, &vIn, enc->rxfrm);         pixelCol = (int)(vOut.X);         pixelRow = (int)(vOut.Y);         moduleStatus = dmtxSymbolModuleStatus(enc->message, enc->region.sizeIdx, symbolRow, symbolCol);         for(i = pixelRow; i < pixelRow + enc->moduleSize; i++) {            for(j = pixelCol; j < pixelCol + enc->moduleSize; j++) {               rgb[0] = ((moduleStatus & DMTX_MODULE_ON_RED) != 0x00) ? 0 : 255;               rgb[1] = ((moduleStatus & DMTX_MODULE_ON_GREEN) != 0x00) ? 0 : 255;               rgb[2] = ((moduleStatus & DMTX_MODULE_ON_BLUE) != 0x00) ? 0 : 255;               dmtxImageSetRgb(enc->image, j, i, rgb);            }         }      }   }}/** * @brief  Initialize encoding channel * @param  channel * @param  codewords * @param  length * @return void */static voidInitChannel(DmtxChannel *channel, unsigned char *codewords, int length){   memset(channel, 0x00, sizeof(DmtxChannel));   channel->encScheme = DmtxSchemeEncodeAscii;   channel->invalid = DMTX_CHANNEL_VALID;   channel->inputPtr = codewords;   channel->inputStop = codewords + length;}/** * @brief  Encode message using single encodation scheme * @param  buf * @param  codewords * @param  length * @param  scheme * @return Encoded length */static intEncodeSingleScheme(unsigned char *buf, unsigned char *codewords, int length, DmtxSchemeEncode scheme){   int size;   DmtxChannel channel;   InitChannel(&channel, codewords, length);   while(channel.inputPtr < channel.inputStop) {      EncodeNextWord(&channel, scheme);      /* DumpChannel(&channel); */      if(channel.invalid != 0) {         fprintf(stderr, "Character \"%c\" not supported by requested encodation scheme\n\n", *channel.inputPtr);         return 0;      }   }   /* DumpChannel(&channel); */   size = channel.encodedLength/12;   memcpy(buf, channel.encodedWords, size);   return size;}/** * @brief  Encode message using best possible encodation (combine schemes) * @param  buf * @param  codewords * @param  length * @return Encoded length of winning channel */static intEncodeAutoBest(unsigned char *buf, unsigned char *codewords, int length){   int targetScheme;   int winnerSize;   DmtxChannelGroup optimal, best;   DmtxChannel *channel, *winner;   /* Intialize optimizing channels and encode first codeword from default ASCII */   for(targetScheme = DmtxSchemeEncodeAscii; targetScheme <= DmtxSchemeEncodeBase256; targetScheme++) {      channel = &(optimal.channel[targetScheme]);      InitChannel(channel, codewords, length);      EncodeNextWord(channel, targetScheme);   }   /* fprintf(stdout,"\nWinners:"); */   /* DumpChannelGroup(&optimal, DmtxSchemeEncodeAscii); */   /* For each remaining word in the input stream, test the efficiency of      getting to this encodation scheme for each input character by      switching here from each of the other channels (which are always      optimally encoded) */   while(optimal.channel[0].inputPtr < optimal.channel[0].inputStop) { /* XXX only tracking first channel */      /* fprintf(stdout,"\n** codeword **\n"); */      for(targetScheme = DmtxSchemeEncodeAscii; targetScheme <= DmtxSchemeEncodeBase256; targetScheme++) {         best.channel[targetScheme] = FindBestChannel(optimal, targetScheme);      }      optimal = best;      /* fprintf(stdout, "\nWinners:"); */      /* DumpChannelGroup(&optimal, 0); */   }   /* Choose a winner now that all channels are finished */   winner = &(optimal.channel[DmtxSchemeEncodeAscii]);   for(targetScheme = DmtxSchemeEncodeAscii + 1; targetScheme <= DmtxSchemeEncodeBase256; targetScheme++) {      if(optimal.channel[targetScheme].invalid != 0)         continue;      if(optimal.channel[targetScheme].encodedLength < winner->encodedLength)         winner = &(optimal.channel[targetScheme]);   }   /* XXX get rid of buf concept and try to do something with channel -> matrix copy instead */   winnerSize = winner->encodedLength/12;   memcpy(buf, winner->encodedWords, winnerSize);   return winnerSize;}/** * @brief  Determine current best channel in encoding process * @param  group * @param  targetScheme * @return Winning channel */static DmtxChannelFindBestChannel(DmtxChannelGroup group, DmtxSchemeEncode targetScheme){   DmtxSchemeEncode encFrom;   DmtxChannel *channel, *winner;   winner = NULL;   for(encFrom = DmtxSchemeEncodeAscii; encFrom <= DmtxSchemeEncodeBase256; encFrom++) {      channel = &(group.channel[encFrom]);      /* If from channel doesn't hold valid data because it couldn't         represent the previous value then skip it */      if(channel->invalid != 0)         continue;      /* If channel has already processed all of its input values then it         cannot be used as a starting point */      if(channel->inputPtr == channel->inputStop)         continue;      EncodeNextWord(channel, targetScheme);      /* If channel scheme can't represent next word then stop for this channel */      if((channel->invalid & DMTX_CHANNEL_UNSUPPORTED_CHAR) != 0) {         winner = channel;         break;      }      /* If channel scheme was unable to unlatch here then skip */      if((channel->invalid & DMTX_CHANNEL_CANNOT_UNLATCH) != 0)         continue;      if(winner == NULL || channel->currentLength < winner->currentLength)         winner = channel;   }   /* DumpChannelGroup(&group, targetScheme); */   return *winner;}/** * @brief  Encode next codeword using requested encodation scheme * @param  channel * @param  targetScheme * @return void */static voidEncodeNextWord(DmtxChannel *channel, DmtxSchemeEncode targetScheme){   /* Change to new encodation scheme if necessary */   if(channel->encScheme != targetScheme) {      ChangeEncScheme(channel, targetScheme, DMTX_UNLATCH_EXPLICIT);      if(channel->invalid != 0)         return;   }   assert(channel->encScheme == targetScheme);   /* Encode next input value */   switch(channel->encScheme) {      case DmtxSchemeEncodeAscii:         EncodeAsciiCodeword(channel);         break;      case DmtxSchemeEncodeC40:         EncodeTripletCodeword(channel);         break;      case DmtxSchemeEncodeText:         EncodeTripletCodeword(channel);         break;      case DmtxSchemeEncodeX12:         EncodeTripletCodeword(channel);         break;      case DmtxSchemeEncodeEdifact:         EncodeEdifactCodeword(channel);         break;      case DmtxSchemeEncodeBase256:         EncodeBase256Codeword(channel);         break;      default:         break;   }}/** * @brief  Encode value using ASCII encodation (standard or extended) * @param  channel * @return void */static voidEncodeAsciiCodeword(DmtxChannel *channel){   unsigned char inputValue, prevValue, prevPrevValue;   int prevIndex;   assert(channel->encScheme == DmtxSchemeEncodeAscii);   inputValue = *(channel->inputPtr);   /* XXX this is problematic ... We should not be looking backward in the      channel to determine what state we're in. Add the necessary logic to      fix the current bug (prevprev != 253) but when rewriting encoder later      make sure double digit ascii as treated as a forward-encoded condition.      i.e., encode ahead of where we currently stand, and not comparable to other      channels because currently sitting between byte boundaries (like the      triplet-based schemes). Much simpler. */   /* XXX another thought on the future rewrite: if adopting a forward-encoding      approach on double digits then the following input situation:         digit digit c40a c40b c40c      would create:         ASCII_double C40_triplet1ab C40_triplet2bc      although it might be more efficient in some cases to do         digit C40_triplet1(digit a) C40_triplet2(a b)      (I can't think of a situation like this, but I can't rule it out either)      Unfortunately the forward encoding approach would never allow ascii to unlatch      between the ASCII_double input words.      One approach that would definitely avoid this is to treat ASCII_dd as a      separate channel when using "--best".  However, when encoding to single-      scheme ascii you would always use the ASCII_dd approach.      This function, EncodeAsciiCodeword(), should have another parameter to flag      whether or not to compress double digits. When encoding in single scheme      ascii, then compress the double digits. If using --best then use both options      as separate channels. */   /* 2nd digit char in a row - overwrite first digit word with combined value */   if(isdigit(inputValue) && channel->currentLength >= channel->firstCodeWord + 12) {      prevIndex = (channel->currentLength - 12)/12;      prevValue = channel->encodedWords[prevIndex] - 1;      prevPrevValue = (prevIndex > channel->firstCodeWord/12) ?            channel->encodedWords[prevIndex-1] : 0;      if(prevPrevValue != 235 && isdigit(prevValue)) {         channel->encodedWords[prevIndex] = 10 * (prevValue - '0') + (inputValue - '0') + 130;         channel->inputPtr++;         return;      }   }   /* Extended ASCII char */   if(inputValue >= 128) {      PushInputWord(channel, DMTX_CHAR_ASCII_UPPER_SHIFT);      IncrementProgress(channel, 12);      inputValue -= 128;   }   /* Normal ASCII char */   else {      inputValue++;   }   PushInputWord(channel, inputValue);   IncrementProgress(channel, 12);   channel->inputPtr++;}/** * @brief  Encode value using C40, Text, or X12 encodation * @param  channel * @return void */static voidEncodeTripletCodeword(DmtxChannel *channel){   int i;   int inputCount;   int tripletCount;   int count;   int outputWords[4];       /* biggest: upper shift to non-basic set */   unsigned char buffer[6];  /* biggest: 2 words followed by 4-word upper shift */   DmtxTriplet triplet;   unsigned char inputWord;   unsigned char *ptr;   assert(channel->encScheme == DmtxSchemeEncodeC40 ||         channel->encScheme == DmtxSchemeEncodeText ||         channel->encScheme == DmtxSchemeEncodeX12);   assert(channel->currentLength <= channel->encodedLength);   /* If there are no pre-encoded codewords then generate some */   if(channel->currentLength == channel->encodedLength) {      assert(channel->currentLength % 12 == 0);      /* Ideally we would only encode one codeword triplet here (the         minimum that you can do at a time) but we can't leave the channel         with the last encoded word as a shift.  The following loop         prevents this condition by encoding until we have a clean break or         until we reach the end of the input data. */      ptr = channel->inputPtr;      tripletCount = 0;      for(;;) {         /* Fill array with at least 3 values (the minimum necessary to            encode a triplet), but possibly up to 6 values due to presence            of upper shifts.  Note that buffer may already contain values            from a previous iteration of the outer loop, and this step            "tops off" the buffer to make sure there are at least 3 values. */         while(tripletCount < 3 && ptr < channel->inputStop) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -