问题
I have written one application for image processing in Java. I have processed the image which is the buffered image and now I want to return the byte[]
for that processed image that is I should get the byte array of binarized image.
Here is my code:
public static byte[][] binarizeImage(BufferedImage bfImage){
int red;
int newPixel;
int h ;
int w ;
int threshold = otsuTreshold(bfImage);
// this function returns the threshold value 199
BufferedImage binarized = new BufferedImage(bfImage.getWidth(), bfImage.getHeight(), bfImage.getType());
for(int i=0; i<bfImage.getWidth(); i++) {
for(int j=0; j<bfImage.getHeight(); j++) {
// Get pixels
red = new Color(bfImage.getRGB(i, j)).getRed();
int alpha = new Color(bfImage.getRGB(i, j)).getAlpha();
if(red > threshold) {
newPixel = 255;
}
else {
newPixel = 0;
}
newPixel = colorToRGB(alpha, newPixel, newPixel, newPixel);
binarized.setRGB(i, j, newPixel);
}
}
Raster raster = binarized.getData();
h = raster.getHeight();
w = raster.getWidth();
byte[][] binarize_image = new byte[w][h];
for(int i=0 ; i<w ; i++)
{
for(int j=0; j<h ; j++)
{
binarize_image[i][j]=raster.getSampleModel(); //error at this line
}
}
return binarize_image;
}
// Convert R, G, B, Alpha to standard 8 bit
private static int colorToRGB(int alpha, int red, int green, int blue) {
int newPixel = 0;
newPixel += alpha;
newPixel = newPixel << 8;
newPixel += red; newPixel = newPixel << 8;
newPixel += green; newPixel = newPixel << 8;
newPixel += blue;
return newPixel;
}
But it is not working. What should I do to convert that buffered image to byte array for the same image data?
回答1:
I am not sure what the term "binarize" means at this context. You seem to just want to filter the image (i.e. cutt-off the red channel based on some threshold) and convert the result to a byte[]
.
Assuming the above is correct then check the code below. It will convert the image to a byte[]
for a 32-bit image. Please take into account the following:
- You do not need to first filter the image and then convert to
byte[]
. You can do that during the conversion. - "Convert RGB to standard 8-bit" : If you mean 8-bit per color channel then this is ok, but if you mean 8-bit per pixel then you are talking about compression/conversion (i.e. you will probably loose some information/quality) in which case you should provide more information about what you want to achieve.
- Your resulting
byte[]
would have a size of4 * width * height
notwidth * height
assuming we are talking about the case of a 32-bit image. If you need to handle other cases you should take into account the available image types supported by theBufferedImage
(or at least only the ones you are interested in).
The code below will print information for each converted pixel like below (Note how the red channel is filtered):
[0,0] Converting [ffaaccee] --> [0, cc, ee, ff]
package imageio.byteconversion;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
public class BufferedImageToBytes {
private static void log(String s) {
System.out.println(s);
}
private static String toByteString(int color) {
// Perform a bitwise AND for convenience while printing.
// Otherwise Integer.toHexString() interprets values as integers and a negative byte 0xFF will be printed as "ffffffff"
return Integer.toHexString(color & 0xFF);
}
public static void main(String[] args) throws IOException {
// Load the image. This expects the image to be in the same package with this class
InputStream stream = BufferedImageToBytes.class.getResourceAsStream("test.png");
BufferedImage image = ImageIO.read(stream);
int iw = image.getWidth();
int ih = image.getHeight();
log("Image loaded succesfully, width=" + iw + " height=" + ih);
stream.close();
log("Image color model: " + image.getColorModel());
log("Image sample model: " + image.getSampleModel());
log("Image raster: " + image.getRaster());
int bands = image.getSampleModel().getNumBands();
log("Color bands: " + bands);
if (bands != 4) {
throw new RuntimeException("The image does not have 4 color bands. Are you sure this is a 32-bit image?");
}
int threshold = 199; // <-- decide your threshold here
byte bytes[] = new byte[4 * iw * ih];
int index = 0;
// note that image is processed row by row top to bottom
for(int y = 0; y < ih; y++) {
for(int x = 0; x < iw; x++) {
// returns a packed pixel where each byte is a color channel
// order is the default ARGB color model
int pixel = image.getRGB(x, y);
// Get pixels
int alpha = (pixel >> 24) & 0xFF;
int red = (pixel >> 16) & 0xFF;
int green = (pixel >> 8) & 0xFF;
int blue = pixel & 0xFF;
// perform filtering here depending on threshold
if (red > threshold) {
red = 255;
} else {
red = 0;
}
log("[" + x + "," + y + "]" + " Converting [" + Integer.toHexString(pixel) + "] --> ["
+ toByteString(red) + ", " + toByteString(green) + ", "
+ toByteString(blue) + ", " + toByteString(alpha)
+ "]");
bytes[index++] = (byte) red;
bytes[index++] = (byte) green;
bytes[index++] = (byte) blue;
bytes[index++] = (byte) alpha;
}
}
}
}
回答2:
Why don't you try to use libs as Catalano Framework. http://code.google.com/p/catalano-framework/
FastBitmap fb = new FastBitmap("c:\\files\\image.jpg");
fb.toGrayscale();
OtsuThreshold otsu = new OtsuThreshold();
otsu.applyInPlace(fb);
int[][] image = new int[fb.getHeight()][fb.getWidth()];
fb.toArrayGray(image);
回答3:
How about:
BufferedImage input;
BufferedImage binary = new BufferedImage(input.getWidth(), input.getHeight(), BufferedImage.TYPE_BYTE_BINARY);
Graphics2D g = binary.createGraphics();
try {
g.drawImage(input, 0, 0, null);
}
finally {
g.dispose();
}
It will not use your otsuTreshold
, and it will (probably) dither the image, but it will do the job of making it binary (black/white only), using a minimal amount of memory.
回答4:
try {
// get the BufferedImage, using the ImageIO class
Bitmap image =
BitmapFactory.decodeStream(getAssets()
.open("aa.bmp"));
marchThroughImage(image);
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
});
}
public void printPixelARGB(int pixel) {
int alpha = (pixel >> 24) & 0xff;
int red = (pixel >> 16) & 0xff;
int green = (pixel >> 8) & 0xff;
int blue = (pixel) & 0xff;
System.out.println("argb: " + alpha + ", " + red + ", " + green + ", " + blue);
}
private void marchThroughImage(Bitmap image) {
int w = image.getWidth();
int h = image.getHeight();
System.out.println("width, height: " + w + ", " + h);
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
System.out.println("x,y: " + j + ", " + i);
int pixel = image.getPixel(j, i);
printPixelARGB(pixel);
System.out.println("");
}
}
}
来源:https://stackoverflow.com/questions/18503412/convert-buffered-image-to-the-2d-byte-array-with-the-same-data