Reading Color-Inverted Barcodes
Reading color‑inverted barcodes
In many real‑world scenarios barcodes are printed white on black (or light on dark) instead of the usual dark bars on a light background.
Such color‑inverted symbols may appear on:
- dark product labels
- UI screenshots with dark themes
- reversed graphics from design tools or printers
By default, most recognition pipelines are tuned for dark‑on‑light images.
Aspose.BarCode for Java lets you explicitly enable inverse image processing for such cases by using:
QualitySettings.setInverseImage(InverseImageMode.ENABLED)on the reader
This article shows how to:
- generate test fixtures with both normal and inverted barcodes
- enable inverted image handling for common symbologies
- apply the same setting to user‑supplied images and various bitmap formats
All code samples are based on the test class:
com.aspose.barcode.guide.recognition.conditions.ReadingColorInvertedExample
You can find the full source on GitHub:
ReadingColorInvertedExample.java
In the snippets below, folderPath represents the path where you store test images in your application.
1. Generating normal and inverted fixtures
The example class generates pairs of images for each symbology:
- positive image: normal dark bars on light background
- inverted image: colors flipped by a helper method
ExampleAssist.invertColors(srcPath, outPath)
Example for Code 128:
private static final String FOLDER =
ExampleAssist.getOrCreateResourceFolderPath("recognition", "color", "color_inverted");
private void generateFixtures() throws Exception {
// Positive Code 128
ExampleAssist.checkOrCreateImage(FOLDER, "Code128.png", out -> {
BarcodeGenerator barcodeGenerator =
new BarcodeGenerator(EncodeTypes.CODE_128, "INVERT IMAGE TEST");
barcodeGenerator.save(out, BarCodeImageFormat.PNG);
});
// Color‑inverted Code 128 (white bars on black background)
ExampleAssist.checkOrCreateImage(FOLDER, "Code128Invert.png", out -> {
String sourcePath = ExampleAssist.pathCombine(FOLDER, "Code128.png");
ExampleAssist.invertColors(sourcePath, out);
});
// The same pattern is used for QR, PDF417 and Data Matrix
}
Key ideas:
- Positive image is generated with
BarcodeGenerator. - Inverted image is created by reading the positive PNG and inverting colors pixel by pixel.
- The
checkOrCreateImagehelper ensures each image is generated only once.
2. Enabling inverse image mode for recognition
To read inverted images, you keep the usual BarCodeReader configuration (path + DecodeType) and then enable inverse processing in QualitySettings:
String imagePath = ExampleAssist.pathCombine(FOLDER, "Code128Invert.png");
BarCodeReader barCodeReader = new BarCodeReader(imagePath, DecodeType.CODE_128);
// Enable inverse image handling for white‑on‑black barcodes
barCodeReader.getQualitySettings().setInverseImage(InverseImageMode.ENABLED);
ExampleAssist.assertRecognizedWithText(
barCodeReader,
"Code128Invert.png",
1,
"INVERT IMAGE TEST"
);
What this does:
InverseImageMode.ENABLEDtells the engine to consider that bars may be lighter than the background.- The engine performs an internal inversion step (or equivalent logic) before decoding.
- The rest of your code stays the same: you still pass the file path and target
DecodeType.
When you have a mix of positive and inverted images in the same flow, it is usually safe to keep inverse mode enabled throughout the session.
3. Applying inverse mode to 2D barcodes
The same setting works uniformly for common 2D symbologies:
- QR (
DecodeType.QR) - PDF417 (
DecodeType.PDF_417) - Data Matrix (
DecodeType.DATA_MATRIX)
The tests in ReadingColorInvertedExample demonstrate this pattern:
// QR, inverted
@Test
public void QRInvert() {
String imagePath = ExampleAssist.pathCombine(FOLDER, "QRInvert.png");
BarCodeReader barCodeReader = new BarCodeReader(imagePath, DecodeType.QR);
barCodeReader.getQualitySettings().setInverseImage(InverseImageMode.ENABLED);
ExampleAssist.assertRecognizedWithText(
barCodeReader,
"QRInvert.png",
1,
"INVERT IMAGE TEST"
);
}
// PDF417, inverted
@Test
public void PDF417Invert() {
String imagePath = ExampleAssist.pathCombine(FOLDER, "PDF417Invert.png");
BarCodeReader barCodeReader = new BarCodeReader(imagePath, DecodeType.PDF_417);
barCodeReader.getQualitySettings().setInverseImage(InverseImageMode.ENABLED);
ExampleAssist.assertRecognizedWithText(
barCodeReader,
"PDF417Invert.png",
1,
"INVERT IMAGE TEST"
);
}
// Data Matrix, inverted
@Test
public void DMInvert() {
String imagePath = ExampleAssist.pathCombine(FOLDER, "DMInvert.png");
BarCodeReader barCodeReader = new BarCodeReader(imagePath, DecodeType.DATA_MATRIX);
barCodeReader.getQualitySettings().setInverseImage(InverseImageMode.ENABLED);
ExampleAssist.assertRecognizedWithText(
barCodeReader,
"DMInvert.png",
1,
"INVERT IMAGE TEST"
);
}
Notes:
- The only difference between these tests is the
DecodeTypeand the file name. - All of them rely on the same quality setting:
InverseImageMode.ENABLED.
4. Working with user images and different formats
In many applications, you do not control how the barcode image is produced.
The example class includes tests that run only if specific user images exist on disk and still use the same inverse mode.
4.1 Data Matrix from an e‑mail example
@Test
public void UserImage_DM_Email() {
String imagePath = ExampleAssist.pathCombine(FOLDER, "datamatrix-generator.png");
if (!ExampleAssist.fileExists(imagePath)) {
ExampleAssist.logWarn("Skip UserImage_DM_Email: not found " + imagePath);
return;
}
BarCodeReader barCodeReader = new BarCodeReader(imagePath, DecodeType.DATA_MATRIX);
barCodeReader.getQualitySettings().setInverseImage(InverseImageMode.ENABLED);
ExampleAssist.assertRecognizedWithText(
barCodeReader,
"datamatrix-generator.png",
1,
"bartoli.giacomo@email.it"
);
}
Pattern:
- Check if the file is actually present.
- Create
BarCodeReaderwith the appropriateDecodeType. - Enable
InverseImageMode.ENABLED. - Validate both barcode presence and decoded text.
4.2 BMP samples (4‑bpp, 1‑bpp) if available
The last two tests cover additional image formats and bit depths:
@Test
public void DMInvert4bpp_BMP_ifExists() {
String imagePath = ExampleAssist.pathCombine(FOLDER, "DMInvert4bpp.bmp");
if (!ExampleAssist.fileExists(imagePath)) {
ExampleAssist.logWarn("Skip DMInvert4bpp_BMP_ifExists: not found " + imagePath);
return;
}
BarCodeReader barCodeReader = new BarCodeReader(imagePath, DecodeType.DATA_MATRIX);
barCodeReader.getQualitySettings().setInverseImage(InverseImageMode.ENABLED);
ExampleAssist.assertRecognizedWithText(
barCodeReader,
"DMInvert4bpp.bmp",
1,
"INVERT IMAGE TEST"
);
}
@Test
public void QRInvert1bpp_BMP_ifExists() {
String imagePath = ExampleAssist.pathCombine(FOLDER, "QRInvert1bpp.bmp");
if (!ExampleAssist.fileExists(imagePath)) {
ExampleAssist.logWarn("Skip QRInvert1bpp_BMP_ifExists: not found " + imagePath);
return;
}
BarCodeReader barCodeReader = new BarCodeReader(imagePath, DecodeType.QR);
barCodeReader.getQualitySettings().setInverseImage(InverseImageMode.ENABLED);
ExampleAssist.assertRecognizedWithText(
barCodeReader,
"QRInvert1bpp.bmp",
1,
"INVERT IMAGE TEST"
);
}
This shows that:
- Inverse image handling is orthogonal to the file format (PNG, BMP, etc.).
- You can still rely on
InverseImageMode.ENABLEDwhen working with indexed or 1‑bit per pixel images, assuming the image data contains a well‑formed inverted symbol.
5. Practical guidelines
When you need to support reversed or color‑inverted barcodes in your application:
-
Enable inverse image mode whenever you expect white‑on‑black or light‑on‑dark barcodes:
barCodeReader.getQualitySettings().setInverseImage(InverseImageMode.ENABLED); -
Keep your DecodeType specific (for example,
CODE_128,QR,PDF_417,DATA_MATRIX) to minimize unnecessary work on unrelated symbologies. -
Reuse the same setting across different parts of your workflow. Inverse mode is transparent for normal images and only helps when inversion is actually present.
-
Test with your real inputs (PNG, BMP, screenshots, scanned PDFs converted to images) to ensure that your pipeline and image pre‑processing preserve enough contrast and resolution.
Summary
- Color‑inverted barcodes are common on dark labels and in UI screenshots.
- Aspose.BarCode for Java supports such images via inverse image processing in
QualitySettings. - The main API hook is
setInverseImage(InverseImageMode.ENABLED)on the reader’s quality settings. - The same approach works for 1D and 2D symbologies and for a variety of image formats and bit depths.
- The accompanying example class demonstrates how to generate fixtures and verify behavior across Code 128, QR, PDF417, and Data Matrix barcodes.
For full context and runnable tests, refer to: