JLChen
2021-05-18 a869383e163a18cdedcf587383c1eca043129754
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
 * Copyright 2012 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
#import "ZXBitMatrix.h"
#import "ZXByteArray.h"
#import "ZXEncodeHints.h"
#import "ZXPDF417.h"
#import "ZXPDF417BarcodeMatrix.h"
#import "ZXPDF417Dimensions.h"
#import "ZXPDF417Writer.h"
 
/**
 * default white space (margin) around the code
 */
const int ZX_PDF417_WHITE_SPACE = 30;
 
@implementation ZXPDF417Writer
 
- (ZXBitMatrix *)encode:(NSString *)contents format:(ZXBarcodeFormat)format width:(int)width height:(int)height
                  hints:(ZXEncodeHints *)hints error:(NSError **)error {
  if (format != kBarcodeFormatPDF417) {
    [NSException raise:NSInvalidArgumentException format:@"Can only encode PDF_417, but got %d", format];
  }
 
  ZXPDF417 *encoder = [[ZXPDF417 alloc] init];
  int margin = ZX_PDF417_WHITE_SPACE;
 
  if (hints != nil) {
    encoder.compact = hints.pdf417Compact;
    encoder.compaction = hints.pdf417Compaction;
    if (hints.pdf417Dimensions != nil) {
      ZXPDF417Dimensions *dimensions = hints.pdf417Dimensions;
      [encoder setDimensionsWithMaxCols:dimensions.maxCols
                                minCols:dimensions.minCols
                                maxRows:dimensions.maxRows
                                minRows:dimensions.minRows];
    }
    if (hints.margin) {
      margin = [hints.margin intValue];
    }
    if (hints.encoding > 0) {
      encoder.encoding = hints.encoding;
    }
  }
 
  return [self bitMatrixFromEncoder:encoder contents:contents width:width height:height margin:margin error:error];
}
 
- (ZXBitMatrix *)encode:(NSString *)contents format:(ZXBarcodeFormat)format width:(int)width height:(int)height error:(NSError **)error {
  return [self encode:contents format:format width:width height:height hints:nil error:error];
}
 
/**
 * Takes encoder, accounts for width/height, and retrieves bit matrix
 */
- (ZXBitMatrix *)bitMatrixFromEncoder:(ZXPDF417 *)encoder
                             contents:(NSString *)contents
                                width:(int)width
                               height:(int)height
                               margin:(int)margin
                                error:(NSError **)error {
  int errorCorrectionLevel = 2;
  if (![encoder generateBarcodeLogic:contents errorCorrectionLevel:errorCorrectionLevel error:error]) {
    return nil;
  }
 
  int lineThickness = 2;
  int aspectRatio = 4;
  NSArray *originalScale = [[encoder barcodeMatrix] scaledMatrixWithXScale:lineThickness yScale:aspectRatio * lineThickness];
  BOOL rotated = NO;
  if ((height > width) ^ ([(ZXByteArray *)originalScale[0] length] < [originalScale count])) {
    originalScale = [self rotateArray:originalScale];
    rotated = YES;
  }
 
  int scaleX = width / [(ZXByteArray *)originalScale[0] length];
  int scaleY = height / [originalScale count];
 
  int scale;
  if (scaleX < scaleY) {
    scale = scaleX;
  } else {
    scale = scaleY;
  }
 
  if (scale > 1) {
    NSArray *scaledMatrix =
      [[encoder barcodeMatrix] scaledMatrixWithXScale:scale * lineThickness yScale:scale * aspectRatio * lineThickness];
    if (rotated) {
      scaledMatrix = [self rotateArray:scaledMatrix];
    }
    return [self bitMatrixFrombitArray:scaledMatrix margin:margin];
  }
  return [self bitMatrixFrombitArray:originalScale margin:margin];
}
 
/**
 * This takes an array holding the values of the PDF 417
 *
 * @param input a byte array of information with 0 is black, and 1 is white
 * @param margin border around the barcode
 * @return BitMatrix of the input
 */
- (ZXBitMatrix *)bitMatrixFrombitArray:(NSArray *)input margin:(int)margin {
  // Creates the bitmatrix with extra space for whtespace
  ZXBitMatrix *output = [[ZXBitMatrix alloc] initWithWidth:[(ZXByteArray *)input[0] length] + 2 * margin height:(int)[input count] + 2 * margin];
  [output clear];
  for (int y = 0, yOutput = output.height - margin; y < [input count]; y++, yOutput--) {
    for (int x = 0; x < [(ZXByteArray *)input[0] length]; x++) {
      // Zero is white in the bytematrix
      if ([(ZXByteArray *)input[y] array][x] == 1) {
        [output setX:x + margin y:yOutput];
      }
    }
  }
  return output;
}
 
/**
 * Takes and rotates the it 90 degrees
 */
- (NSArray *)rotateArray:(NSArray *)bitarray {
  NSMutableArray *temp = [NSMutableArray array];
  for (int i = 0; i < [(ZXByteArray *)bitarray[0] length]; i++) {
    [temp addObject:[[ZXByteArray alloc] initWithLength:(unsigned int)[bitarray count]]];
  }
 
  for (int ii = 0; ii < [bitarray count]; ii++) {
    // This makes the direction consistent on screen when rotating the
    // screen;
    int inverseii = (int)[bitarray count] - ii - 1;
    for (int jj = 0; jj < [(ZXByteArray *)bitarray[0] length]; jj++) {
      ZXByteArray *b = temp[jj];
      b.array[inverseii] = [(ZXByteArray *)bitarray[ii] array][jj];
    }
  }
  return temp;
}
 
@end