Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * Copyright 2013 ZXing authors
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import "ZXBitMatrix.h"
  17. #import "ZXByteMatrix.h"
  18. #import "ZXDataMatrixDefaultPlacement.h"
  19. #import "ZXDataMatrixErrorCorrection.h"
  20. #import "ZXDataMatrixHighLevelEncoder.h"
  21. #import "ZXDataMatrixSymbolInfo.h"
  22. #import "ZXDataMatrixWriter.h"
  23. #import "ZXDimension.h"
  24. #import "ZXEncodeHints.h"
  25. @implementation ZXDataMatrixWriter
  26. - (ZXBitMatrix *)encode:(NSString *)contents format:(ZXBarcodeFormat)format width:(int)width height:(int)height error:(NSError **)error {
  27. return [self encode:contents format:format width:width height:height hints:nil error:error];
  28. }
  29. - (ZXBitMatrix *)encode:(NSString *)contents format:(ZXBarcodeFormat)format width:(int)width height:(int)height hints:(ZXEncodeHints *)hints error:(NSError **)error {
  30. if (contents.length == 0) {
  31. [NSException raise:NSInvalidArgumentException format:@"Found empty contents"];
  32. }
  33. if (format != kBarcodeFormatDataMatrix) {
  34. [NSException raise:NSInvalidArgumentException format:@"Can only encode kBarcodeFormatDataMatrix"];
  35. }
  36. if (width < 0 || height < 0) {
  37. [NSException raise:NSInvalidArgumentException
  38. format:@"Requested dimensions are too small: %dx%d", width, height];
  39. }
  40. // Try to get force shape & min / max size
  41. ZXDataMatrixSymbolShapeHint shape = ZXDataMatrixSymbolShapeHintForceNone;
  42. ZXDimension *minSize = nil;
  43. ZXDimension *maxSize = nil;
  44. if (hints != nil) {
  45. shape = hints.dataMatrixShape;
  46. #pragma GCC diagnostic push
  47. #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  48. ZXDimension *requestedMinSize = hints.minSize;
  49. #pragma GCC diagnostic pop
  50. if (requestedMinSize != nil) {
  51. minSize = requestedMinSize;
  52. }
  53. #pragma GCC diagnostic push
  54. #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  55. ZXDimension *requestedMaxSize = hints.maxSize;
  56. #pragma GCC diagnostic pop
  57. if (requestedMaxSize != nil) {
  58. maxSize = requestedMaxSize;
  59. }
  60. }
  61. //1. step: Data encodation
  62. NSString *encoded = [ZXDataMatrixHighLevelEncoder encodeHighLevel:contents shape:shape minSize:minSize maxSize:maxSize];
  63. ZXDataMatrixSymbolInfo *symbolInfo = [ZXDataMatrixSymbolInfo lookup:(int)encoded.length shape:shape minSize:minSize maxSize:maxSize fail:YES];
  64. //2. step: ECC generation
  65. NSString *codewords = [ZXDataMatrixErrorCorrection encodeECC200:encoded symbolInfo:symbolInfo];
  66. //3. step: Module placement in Matrix
  67. ZXDataMatrixDefaultPlacement *placement = [[ZXDataMatrixDefaultPlacement alloc] initWithCodewords:codewords numcols:symbolInfo.symbolDataWidth numrows:symbolInfo.symbolDataHeight];
  68. [placement place];
  69. //4. step: low-level encoding
  70. return [self encodeLowLevel:placement symbolInfo:symbolInfo width:width height:height];
  71. }
  72. /**
  73. * Encode the given symbol info to a bit matrix.
  74. *
  75. * @param placement The DataMatrix placement.
  76. * @param symbolInfo The symbol info to encode.
  77. * @return The bit matrix generated.
  78. */
  79. - (ZXBitMatrix *)encodeLowLevel:(ZXDataMatrixDefaultPlacement *)placement symbolInfo:(ZXDataMatrixSymbolInfo *)symbolInfo width:(int)width height:(int)height {
  80. int symbolWidth = symbolInfo.symbolDataWidth;
  81. int symbolHeight = symbolInfo.symbolDataHeight;
  82. ZXByteMatrix *matrix = [[ZXByteMatrix alloc] initWithWidth:symbolInfo.symbolWidth height:symbolInfo.symbolHeight];
  83. int matrixY = 0;
  84. for (int y = 0; y < symbolHeight; y++) {
  85. // Fill the top edge with alternate 0 / 1
  86. int matrixX;
  87. if ((y % symbolInfo.matrixHeight) == 0) {
  88. matrixX = 0;
  89. for (int x = 0; x < symbolInfo.symbolWidth; x++) {
  90. [matrix setX:matrixX y:matrixY boolValue:(x % 2) == 0];
  91. matrixX++;
  92. }
  93. matrixY++;
  94. }
  95. matrixX = 0;
  96. for (int x = 0; x < symbolWidth; x++) {
  97. // Fill the right edge with full 1
  98. if ((x % symbolInfo.matrixWidth) == 0) {
  99. [matrix setX:matrixX y:matrixY boolValue:YES];
  100. matrixX++;
  101. }
  102. [matrix setX:matrixX y:matrixY boolValue:[placement bitAtCol:x row:y]];
  103. matrixX++;
  104. // Fill the right edge with alternate 0 / 1
  105. if ((x % symbolInfo.matrixWidth) == symbolInfo.matrixWidth - 1) {
  106. [matrix setX:matrixX y:matrixY boolValue:(y % 2) == 0];
  107. matrixX++;
  108. }
  109. }
  110. matrixY++;
  111. // Fill the bottom edge with full 1
  112. if ((y % symbolInfo.matrixHeight) == symbolInfo.matrixHeight - 1) {
  113. matrixX = 0;
  114. for (int x = 0; x < symbolInfo.symbolWidth; x++) {
  115. [matrix setX:matrixX y:matrixY boolValue:YES];
  116. matrixX++;
  117. }
  118. matrixY++;
  119. }
  120. }
  121. return [self convertByteMatrixToBitMatrix:matrix width:width height:height];
  122. }
  123. /**
  124. * Convert the ZXByteMatrix to ZXBitMatrix.
  125. *
  126. * @param input The input matrix.
  127. * @return The output matrix.
  128. */
  129. - (ZXBitMatrix *)convertByteMatrixToBitMatrix:(ZXByteMatrix *)input width:(int)width height:(int)height {
  130. int inputWidth = input.width;
  131. int inputHeight = input.height;
  132. int outputWidth = MAX(width, inputWidth);
  133. int outputHeight = MAX(height, inputHeight);
  134. int multiple = MIN(outputWidth / inputWidth, outputHeight / inputHeight);
  135. int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
  136. int topPadding = (outputHeight - (inputHeight * multiple)) / 2;
  137. ZXBitMatrix *output = [[ZXBitMatrix alloc] initWithWidth:outputWidth height:outputHeight];
  138. for (int inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {
  139. for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {
  140. if ([input getX:inputX y:inputY] == 1) {
  141. [output setRegionAtLeft:outputX top:outputY width:multiple height:multiple];
  142. }
  143. }
  144. }
  145. return output;
  146. }
  147. @end