I try to make a BMP file from BufferedImage. Here is function with that I try to write the header and pixels in bmp file.
I have a mistake but I can't find that. I need your help.
static void writeToBMP(BufferedImage img, String name)
{
//File header
int bfType = 0x424d;
int bfSize = (img.getHeight()*img.getWidth()*3)+54; // File size
short bfReserved1 = 0; // Reserved
short bfReserved2 = 0;
int bfOfBytes = 54; // Header size
//Header info
int biSize = 40; // Header 2 size
int biWidth = img.getWidth(); // Width in pixels
int biHeight = img.getHeight(); // Height in pixels
short biPlanes = 1; // Nr of planes
short biBitCount = 24; // Nr bites per pixel
int biCompression = 0;
int biSizeImage = (img.getHeight()*img.getWidth()*3); // Image size
int biXPelsPerMeter = 0;
int biYPelsPerMeter = 0;
int biClrUsed = 0;
int biClrImportant = 0;
File file = new File(name);
try {
OutputStream stream = new FileOutputStream(file);
fOut = new DataOutputStream(stream);
fOut.writeShort(bfType);
fOut.writeInt(bfSize);
fOut.writeShort(bfReserved1);
fOut.writeShort(bfReserved2);
fOut.writeInt(bfOfBytes);
//Write Header Info
fOut.writeInt(biSize);
fOut.writeInt(biWidth);
fOut.writeInt(biHeight);
fOut.writeShort(biPlanes);
fOut.writeShort(biBitCount);
fOut.writeInt(biCompression);
fOut.writeInt(biSizeImage);
fOut.writeInt(biXPelsPerMeter);
fOut.writeInt(biYPelsPerMeter);
fOut.writeInt(biClrUsed);
fOut.writeInt(biClrImportant);
for(int x=0; x<img.getWidth(); x++)
{
for(int y=0; y<img.getHeight(); y++)
{
Color c = new Color(img.getRGB(x,y));
fOut.writeByte(c.getRed());
fOut.writeByte(c.getBlue());
fOut.writeByte(c.getGreen());
}
}
fOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
I tried to write only header, and header size = 54 bytes.
I don't know if I calculate correct the bfSize and biSizeImage.
Try using ImageIO
File outImage = new File(name);
ImageIO.write(img, "bmp", outImage);
To resolve my problem I need to use LITTLE_ENDIAN byte order. For this I use:
ByteBuffer buffer = ByteBuffer.allocate(54);
buffer.putInt(bfSize);
buffer.putShort(bfReserved1);
buffer.putShort(bfReserved2);
buffer.putInt(bfOfBytes);
buffer.putInt(biSize);
buffer.putInt(biWidth);
buffer.putInt(biHeight);
buffer.putShort(biPlanes);
buffer.putShort(biBitCount);
buffer.putInt(biSizeImage);
buffer.putInt(biXPelsPerMeter);
buffer.putInt(biYPelsPerMeter);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.flip();
Related
This is the code how I convert BufferedImage to byte array:
public void parseBufferedImage(BufferedImage image) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
Color color = new Color(image.getRGB(x, y), true);
outputStream.write(color.getRed());
outputStream.write(color.getGreen());
outputStream.write(color.getBlue());
outputStream.write(color.getAlpha());
}
}
image.flush();
byte[] data = outputStream.toByteArray();
}
I need to convert byte[] data back to an image, but I have only byte[] array so I do not know image size.
I want to save byte[] as a png, so I would be open to suggestions of another method.
I have a little problem here if someone could help me I will be really glad.
I'm trying to make the next operations
Read an BMP image
Convert the image into a byte[]
Rotate the image with 90 degree(the byte array)
And write a new image in some folder
My problem is... In the moment when I'm trying to write the new image I have some problem with BMP header and I don't know why. Please give me some advice if anyone know the answear.
Convert the image into byte[]
private static byte[] convertAnImageToPixelsArray(File file) throws FileNotFoundException {
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
try {
for (int readNum; (readNum = fis.read(buf)) != -1; ) {
bos.write(buf, 0, readNum);
}
} catch (IOException ex) {
Logger.getLogger(ConvertImage.class.getName()).log(Level.SEVERE, null, ex);
}
return bos.toByteArray();
}
Rotate
private static byte[] rotate(double angle, byte[] pixels, int width, int height) {
final double radians = Math.toRadians(angle), cos = Math.cos(radians), sin = Math.sin(radians);
final byte[] pixels2 = new byte[pixels.length];
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
final int
centerx = width / 2,
centery = height / 2,
m = x - centerx,
n = y - centery,
j = ((int) (m * cos + n * sin)) + centerx,
k = ((int) (n * cos - m * sin)) + centery;
if (j >= 0 && j < width && k >= 0 && k < height)
pixels2[(y * width + x)] = pixels[(k * width + j)];
}
}
arraycopy(pixels2, 0, pixels, 0, pixels.length);
return pixels2;
}
Convert the byte[] into image
private static void convertArrayPixelsIntoImage(byte[] bytes) throws IOException {
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
Iterator<?> readers = ImageIO.getImageReadersByFormatName("bmp");
ImageReader reader = (ImageReader) readers.next();
Object source = bis;
ImageInputStream iis = ImageIO.createImageInputStream(source);
reader.setInput(iis, true);
ImageReadParam param = reader.getDefaultReadParam();
Image image = reader.read(0, param);
BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bufferedImage.createGraphics();
g2.drawImage(image, null, null);
File imageFile = new File("Images/Output.bmp");
ImageIO.write(bufferedImage, "bmp", imageFile);
}
Main:
public static void main(String[] args) throws IOException {
File file = new File("Images/Input-1.bmp");
Image img = ImageIO.read(file);
convertArrayPixelsIntoImage(rotate(90,convertAnImageToPixelsArray(file),img.getWidth(null),img.getHeight(null)));
}
Here it's the error message:
Exception in thread "main" javax.imageio.IIOException: Unable to read the image header.
Any suggestions?
The problem is that you're not taking into account the structure of the BMP file when you are rotating the image.
You're just reading a byte[] from the file, as you could from any file - it's just a stream of bytes.
But in your rotate method, you're assuming that the pixel values are:
1 byte per pixel;
Starting at the start of the array.
This isn't the case. Aside from the fact that each pixel will almost certainly be encoded by multiple bytes, the BMP file format starts with a header, and other metadata.
Whilst you obviously could work out how to decode the data correctly, I would strongly discourage it. You're already reading the image using ImageIO (Image img = ImageIO.read(file);), so you've got no need to reinvent the wheel: just use Java's existing image manipulation functionality.
You missed that the BMP image has a header like any other format. When you try to rotate the image, you are changing the bytes sequance, so the header loses in other place instead, of beginning. Try to extract first 54 bytes to another array, rotate others and then write to file header at first and ather bytes at second
I'm trying to implement a DCT on an image, and so far I have only been able to successfully read an image, grayscale it, turn it into a byte array and then output the byte array as an image. This works fine. However, in order to work on the image I need to convert the byte array to an int array and then back again, and this is where the problem comes in.
This first part reads the image and converts the image to grayscale.
BufferedImage image = ImageIO.read(new File("C:\\Users\\A00226084\\Desktop\\image.jpg"));
int width = image.getWidth();
int height = image.getHeight();
for(int i=0; i<height; i++){
for(int j=0; j<width; j++){
Color c = new Color(image.getRGB(j, i));
int red = (int)(c.getRed() * 0.299);
int green = (int)(c.getGreen() * 0.587);
int blue = (int)(c.getBlue() *0.114);
Color newColor = new Color(red+green+blue,
red+green+blue,red+green+blue);
image.setRGB(j,i,newColor.getRGB());
}
}
This part converts the image to a byte array.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", baos);
byte[] pixels = baos.toByteArray();
This part then converts the byte array to an int array. I have manually done the wrapping because nothing else worked.
for(int i = 0; i < pixels.length; i ++){
if(pixels[i] < 0){
byteConverted[i] = 127 + (128 - (pixels[i] * -1));
}else{
byteConverted[i] = pixels[i];
}
}
This part converts the int array back to a byte array, somewhere between the byte > int and int > byte conversions that everything goes wrong. I have output both the before and after byte array to a file and they are identical, so I don't know why I get 'image == null' instead of the image.
for(int i = 0; i < pixels.length; i ++){
if(byteConverted[i] > 127){
pixels[i] = (byte) ( -128 + (byteConverted[i] - 127));
}else{
pixels[i] = (byte) byteConverted[i];
}
}
write2("final byte array.txt", pixels);
ByteArrayInputStream bais = new ByteArrayInputStream(pixels);
try {
BufferedImage img = ImageIO.read(bais);
System.out.println("Image Out");
System.out.println(pixels.length);
ImageIO.write(img, "jpg", new File("C:\\Users\\A00226084\\Desktop\\newImage.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
I have a colour image that is been stored in a 3D array and now I want to display this data or the image on to a JPanel. My code read function is as follows :
public void readImage(String filename) throws Exception {
String filenameExtension = filename.substring(filename.lastIndexOf('.')+1);
File fileImage = FileChosen;
Iterator imageReaders = ImageIO.getImageReadersBySuffix(filenameExtension);
ImageReader imageReader;
if(imageReaders.hasNext())
imageReader = (ImageReader)imageReaders.next();
else
throw new IOException("Unsupported image format");
FileImageInputStream imageInputStream = new FileImageInputStream(fileImage);
imageReader.setInput(imageInputStream);
ImgWidth = imageReader.getWidth(0);
ImgHeight = imageReader.getHeight(0);
BufferedImage bufImage = imageReader.read(0);
imageInputStream.close();
WritableRaster wRaster = bufImage.getRaster();
//int numBands = wRaster.getNumBands();
System.out.println(ImgWidth);
System.out.println(ImgHeight);
imageArray = (new double[ImgHeight][ImgWidth][ColourLevels]);
// get the samples and normalize to between 0 and 1
for(int row = 0; row < ImgHeight; row++)
for(int col = 0; col < ImgWidth; col++)
for(int level = 0; level < ColourLevels; level++)
imageArray[row][col][level] = (wRaster.getSample((col), (row), level) / 255.0);
} // end read method`
Now I want to print the data stored in the imageArray[][][] in to a panel, how can I do that?
hey i have using j2me to read an image
i want to do some process on that image like Darkenes , lightens
i already read image as an input stream
InputStream iStrm = getClass().getResourceAsStream("/earth.PNG");
ByteArrayOutputStream bStrm = new ByteArrayOutputStream();
int ch;
while ((ch = iStrm.read()) != -1){
bStrm.write(ch);
byte imageData[] = bStrm.toByteArray();
Image im = Image.createImage(imageData, 0, imageData.length);
how can i get RGB values or how can i add some values to the array of pixles
imageData[] so it can more lightens or darkness ,
is there header data including in the input stream i had read , that cause me error when iam adding some values to it ?
I think you should be able to do the following:
int width = im.getWidth();
int height = im.getHeight();
int[] rgbData = new int[width*height]; // since we are working with rgba
im.getRGB(rgbData, 0, width, 0, 0, width, height);
// now, the data is stored in each integer as 0xAARRGGBB,
// so high-order bits are alpha channel for each integer
Now, if you want to put them into three arrays, one for each channel, you could do the following:
int red[][] = new int[width][height];
int green[][] = new int[width][height];
int blue[][] = new int[width][height];
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
red[i][j] = rgb[i*width + j] & 0xFF0000;
green[i][j] = rgb[i*width + j] & 0xFF00;
blue[i][j] = rgb[i+width + j] & 0xFF;
}
}