I'm using ZXing code to create QR bar codes. I got the example code from here working: http://www.vineetmanohar.com/2010/09/java-barcode-api/ and the PNG image looks good, black and white as expected.
In the example codes comments it mentions I could use tiff or jpeg format so I changed the imgeFormat variable to jpeg. A correct looking QR code image is created but instead of being black and white the 开发者_如何学运维"white" part is a peach color and the "black" part is a blue color.
I cut and past the ZXing MatrixToImageWriter code into my code and set the colors instead of using the int BLACK = 0xFF000000; and int WHITE = 0xFFFFFFFF; I found that by replacing the BLACK variable with with 0x00000000 I got black on my image, but I have been unable to find a value for the WHITE variable that give me a white.
Attached is the odd colored QR barcode. Oops, I'm too new of a user to attach an image. Hopefully this link to imgur.com works: http://imgur.com/QnNXO
Here is the Java code:
package zxing_qr;
import java.io.File;
import java.io.FileOutputStream;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
// by passing MatrixToImageWriter call
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.Graphics2D;
public class Main {
public static void main(String[] args) {
//String text = "98376373783"; // this is the text that we want to encode
String text = "blahblahblah"; // this is the text that we want to encode
int width = 400;
int height = 300; // change the height and width as per your requirement
// (ImageIO.getWriterFormatNames() returns a list of supported formats)
String imageFormat = "jpg"; // could be "gif", "tiff", "jpeg"
try {
BitMatrix bitMatrix = new QRCodeWriter().encode(text, BarcodeFormat.QR_CODE, width, height);
MatrixToImageWriter.writeToStream(bitMatrix, imageFormat, new FileOutputStream(new File("qrcode_97802017507991.jpg")));
} catch (WriterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} // end main function
} // end main class
I have stumbled upon the answer. Inside the ZXing class MatrixToImageWriter a BufferedImage object is created with BufferedImage.TYPE_INT_ARGB as the 3rd argument. By changing this to BufferedImage.TYPE_INT_RGB the colors for jpeg are turning out black and white as expected.
Instead of hacking ZXing classes you may also programmatically convert the image pixels to RGB:
...
final BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(matrix);
final BufferedImage rgbImage = convertARGBtoRGB(bufferedImage);
...
private static BufferedImage convertARGBtoRGB(final BufferedImage argb) {
assert argb.getType() == BufferedImage.TYPE_INT_ARGB;
final int width = argb.getWidth();
final int height = argb.getHeight();
final BufferedImage rgbImage= new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
rgbImage.setRGB(x, y, argb.getRGB(x, y));
}
}
return rgbImage;
}
Or you can make your own conversion from BitMatrix
to buffered image
private static BufferedImage drawCodeOnImage(BitMatrix bitMatrix) {
if (bitMatrix == null) {
throw new IllegalArgumentException("BitMatrix cannot be null");
}
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_INDEXED);
image.createGraphics();
Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, width, height);
graphics.setColor(Color.BLACK);
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
if (bitMatrix.get(i, j)) {
graphics.fillRect(i, j, 1, 1);
}
}
}
return image;
}
I used BufferedImage.TYPE_BYTE_INDEXED
because with GIF format it is faster to write to OutputStream.
The color defined as 0x00.. is transparent, the color defined as 0xFF... is opaque acording to Android colors. These colors are used already in the call
MatrixToImageWriter.writeToStream(bitMatrix, imageFormat, new FileOutputStream(new File("qrcode_97802017507991.jpg")));
as the default configuration.
精彩评论