0
# Image Processing
1
2
ZXing-C++ provides flexible image data handling through the ImageView class, supporting multiple pixel formats with built-in transformations and optimization features for barcode detection.
3
4
## ImageView Class
5
6
A non-owning view of image data that provides format-agnostic access to pixel information.
7
8
```cpp { .api }
9
class ImageView {
10
public:
11
ImageView(const uint8_t* data, int width, int height, ImageFormat format,
12
int rowStride = 0, int pixStride = 0);
13
14
int width() const;
15
int height() const;
16
int pixStride() const;
17
int rowStride() const;
18
ImageFormat format() const;
19
20
const uint8_t* data(int x, int y) const;
21
22
ImageView cropped(int left, int top, int width, int height) const;
23
ImageView rotated(int degree) const;
24
ImageView subsampled(int scale) const;
25
};
26
```
27
28
### Constructor
29
30
```cpp { .api }
31
ImageView(const uint8_t* data, int width, int height, ImageFormat format,
32
int rowStride = 0, int pixStride = 0);
33
```
34
35
Creates a view of existing image data without copying.
36
37
**Parameters:**
38
- `data`: Pointer to raw image data (not owned by ImageView)
39
- `width`: Image width in pixels
40
- `height`: Image height in pixels
41
- `format`: Pixel format describing data layout
42
- `rowStride`: Optional bytes per row (default: width × pixStride)
43
- `pixStride`: Optional bytes per pixel (default: calculated from format)
44
45
### Property Methods
46
47
```cpp { .api }
48
int width() const;
49
int height() const;
50
int pixStride() const;
51
int rowStride() const;
52
ImageFormat format() const;
53
```
54
55
Get image dimensions and format information.
56
57
### Data Access
58
59
```cpp { .api }
60
const uint8_t* data(int x, int y) const;
61
```
62
63
Get pointer to pixel data at specified coordinates.
64
65
**Parameters:**
66
- `x`: X coordinate (0 to width-1)
67
- `y`: Y coordinate (0 to height-1)
68
69
**Returns:** Pointer to pixel data at (x,y)
70
71
### Transformation Methods
72
73
```cpp { .api }
74
ImageView cropped(int left, int top, int width, int height) const;
75
ImageView rotated(int degree) const;
76
ImageView subsampled(int scale) const;
77
```
78
79
Create transformed views of the image data without copying.
80
81
## Image Formats
82
83
```cpp { .api }
84
enum class ImageFormat : uint32_t {
85
None = 0,
86
Lum = 0x01000000, // Grayscale (1 byte per pixel)
87
RGB = 0x03000102, // Red-Green-Blue (3 bytes per pixel)
88
BGR = 0x03020100, // Blue-Green-Red (3 bytes per pixel)
89
RGBX = 0x04000102, // RGB + unused byte (4 bytes per pixel)
90
XRGB = 0x04010203, // Unused + RGB (4 bytes per pixel)
91
BGRX = 0x04020100, // BGR + unused byte (4 bytes per pixel)
92
XBGR = 0x04030201, // Unused + BGR (4 bytes per pixel)
93
};
94
```
95
96
### Format Helper Functions
97
98
```cpp { .api }
99
constexpr int PixStride(ImageFormat format);
100
constexpr int RedIndex(ImageFormat format);
101
constexpr int GreenIndex(ImageFormat format);
102
constexpr int BlueIndex(ImageFormat format);
103
104
constexpr uint8_t RGBToLum(unsigned r, unsigned g, unsigned b);
105
```
106
107
## Usage Examples
108
109
### Basic Image View Creation
110
111
```cpp
112
#include "ImageView.h"
113
114
using namespace ZXing;
115
116
// Grayscale image (most efficient for barcode reading)
117
const uint8_t* grayData = /* your grayscale image data */;
118
ImageView grayView(grayData, 640, 480, ImageFormat::Lum);
119
120
// RGB image
121
const uint8_t* rgbData = /* your RGB image data */;
122
ImageView rgbView(rgbData, 640, 480, ImageFormat::RGB);
123
124
// RGBA image (ignoring alpha channel)
125
const uint8_t* rgbaData = /* your RGBA image data */;
126
ImageView rgbaView(rgbaData, 640, 480, ImageFormat::RGBX);
127
```
128
129
### Custom Stride Configuration
130
131
```cpp
132
// Image with custom row padding
133
int width = 320;
134
int height = 240;
135
int rowStride = 352; // Padded to 32-byte alignment
136
const uint8_t* paddedData = /* padded image data */;
137
138
ImageView paddedView(paddedData, width, height, ImageFormat::RGB, rowStride);
139
140
// Non-contiguous pixel data (e.g., YUV planar format converted to RGB)
141
int pixStride = 4; // Skip every 4th byte
142
ImageView strideView(data, width, height, ImageFormat::RGB, 0, pixStride);
143
```
144
145
### Image Transformations
146
147
```cpp
148
ImageView originalView(imageData, 800, 600, ImageFormat::RGB);
149
150
// Crop to region of interest
151
ImageView cropped = originalView.cropped(100, 50, 400, 300);
152
153
// Rotate image for different orientations
154
ImageView rotated90 = originalView.rotated(90);
155
ImageView rotated180 = originalView.rotated(180);
156
ImageView rotated270 = originalView.rotated(270);
157
158
// Downsample for faster processing
159
ImageView halfSize = originalView.subsampled(2); // 400x300
160
ImageView quarterSize = originalView.subsampled(4); // 200x150
161
162
// Chain transformations
163
ImageView processed = originalView
164
.cropped(50, 50, 700, 500)
165
.rotated(90)
166
.subsampled(2);
167
```
168
169
### Working with Different Color Formats
170
171
```cpp
172
// Convert RGB to BGR ordering (common format conversion)
173
void convertRGBtoBGR(const uint8_t* rgbData, uint8_t* bgrData, int pixels) {
174
for (int i = 0; i < pixels; ++i) {
175
bgrData[i*3 + 0] = rgbData[i*3 + 2]; // Blue = Red
176
bgrData[i*3 + 1] = rgbData[i*3 + 1]; // Green = Green
177
bgrData[i*3 + 2] = rgbData[i*3 + 0]; // Red = Blue
178
}
179
}
180
181
// Handle different platform formats
182
#ifdef PLATFORM_USES_BGR
183
ImageView platformView(data, width, height, ImageFormat::BGR);
184
#else
185
ImageView platformView(data, width, height, ImageFormat::RGB);
186
#endif
187
```
188
189
### Grayscale Conversion
190
191
```cpp
192
// Convert RGB to grayscale for optimal barcode reading performance
193
std::vector<uint8_t> convertToGrayscale(const uint8_t* rgbData, int width, int height) {
194
std::vector<uint8_t> grayData(width * height);
195
196
for (int i = 0; i < width * height; ++i) {
197
uint8_t r = rgbData[i * 3 + 0];
198
uint8_t g = rgbData[i * 3 + 1];
199
uint8_t b = rgbData[i * 3 + 2];
200
grayData[i] = RGBToLum(r, g, b);
201
}
202
203
return grayData;
204
}
205
206
// Usage
207
std::vector<uint8_t> grayData = convertToGrayscale(rgbData, width, height);
208
ImageView grayView(grayData.data(), width, height, ImageFormat::Lum);
209
```
210
211
### Memory Layout Examples
212
213
```cpp
214
// Tightly packed RGB data
215
// Memory: [R1,G1,B1,R2,G2,B2,R3,G3,B3,...]
216
ImageView packedRGB(data, width, height, ImageFormat::RGB);
217
218
// RGB with alpha channel (RGBA)
219
// Memory: [R1,G1,B1,A1,R2,G2,B2,A2,...]
220
ImageView rgba(data, width, height, ImageFormat::RGBX);
221
222
// Planar RGB data would need conversion before using ImageView
223
// R plane: [R1,R2,R3,...], G plane: [G1,G2,G3,...], B plane: [B1,B2,B3,...]
224
// This format is not directly supported - convert to interleaved first
225
```
226
227
### Integration with Image Libraries
228
229
```cpp
230
// Example with OpenCV
231
#ifdef USE_OPENCV
232
#include <opencv2/opencv.hpp>
233
234
ImageView fromOpenCV(const cv::Mat& mat) {
235
ImageFormat format;
236
switch (mat.channels()) {
237
case 1: format = ImageFormat::Lum; break;
238
case 3: format = ImageFormat::BGR; break; // OpenCV uses BGR
239
case 4: format = ImageFormat::BGRX; break;
240
default: throw std::runtime_error("Unsupported channel count");
241
}
242
243
return ImageView(mat.data, mat.cols, mat.rows, format, mat.step);
244
}
245
#endif
246
247
// Example with custom image loader
248
ImageView loadImage(const std::string& filename) {
249
// Load image using your preferred library (STB, FreeImage, etc.)
250
int width, height, channels;
251
uint8_t* data = loadImageData(filename, &width, &height, &channels);
252
253
ImageFormat format = (channels == 1) ? ImageFormat::Lum : ImageFormat::RGB;
254
return ImageView(data, width, height, format);
255
}
256
```
257
258
### Performance Optimization
259
260
```cpp
261
// Use grayscale images for best performance
262
ImageView optimizedView(grayData, width, height, ImageFormat::Lum);
263
264
// Crop to barcode region if known approximately
265
ImageView regionView = fullImage.cropped(x, y, regionWidth, regionHeight);
266
267
// Downsample large images for initial detection
268
ImageView quickScan = fullImage.subsampled(4);
269
Result quickResult = ReadBarcode(quickScan);
270
271
if (quickResult.isValid()) {
272
// Found something, try full resolution in the detected area
273
Position pos = quickResult.position();
274
ImageView fullResRegion = fullImage.cropped(
275
pos.topLeft().x * 4 - 50, // Scale back up and add margin
276
pos.topLeft().y * 4 - 50,
277
200, 200
278
);
279
Result finalResult = ReadBarcode(fullResRegion);
280
}
281
```
282
283
## Format Conversion Utilities
284
285
```cpp
286
// Get format information
287
ImageFormat format = ImageFormat::RGB;
288
int pixelSize = PixStride(format); // Returns 3 for RGB
289
int redOffset = RedIndex(format); // Returns 0 for RGB
290
int greenOffset = GreenIndex(format); // Returns 1 for RGB
291
int blueOffset = BlueIndex(format); // Returns 2 for RGB
292
293
// Convert color to grayscale
294
uint8_t gray = RGBToLum(255, 128, 64); // Returns grayscale value
295
```
296
297
## Best Practices
298
299
1. **Use grayscale images** when possible - significantly faster processing
300
2. **Choose appropriate transformations** - crop before rotate/subsample for efficiency
301
3. **Validate image data lifetime** - ImageView doesn't own the data pointer
302
4. **Consider memory alignment** - some platforms benefit from aligned row strides
303
5. **Test format compatibility** - verify your image data matches the specified format
304
6. **Use subsampling for large images** - start with lower resolution for better performance
305
7. **Crop to regions of interest** - reduce processing area when barcode location is known