0

I'm trying to read a 256x256 image using ImageIO.read, transform it into a ByteArray, then into a BufferedImage, and back into an image file using ImageIO.write. It all seems to work as it should, but the final image is quite corrupted (although clearly still based on the original image. I can't find what's wrong in the process, I am suspicious of the scansize parameter, which I don't completely understand.

The idea is to manipulate pixels in between the reading and writing, but at the moment I can't even recreate the original image back into itself.

I attach the original image and the processed one below:

import java.awt.image.BufferedImage
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.IOException
import javax.imageio.ImageIO

fun main(args: Array<String>) {
    val bImage = ImageIO.read(File("original.tiff"))
    val bos = ByteArrayOutputStream()
    ImageIO.write(bImage, "tiff", bos)
    val data = bos.toByteArray()
    val width = 256
    val height = 256
    val bytesPerPixel = 3
    val len = width * height * bytesPerPixel
    val image = BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)
    val arr = IntArray(len)

    for (i in 0 until len) arr[i] = data.get(i).toInt()

    image.setRGB(0, 0, width, height, arr, 0, 256) // Seems like something is wrong here

    try {
        ImageIO.write(image, "jpg", File("converted-grayscale-002.jpg"))
    } catch (e: IOException) {
        System.err.println("IOException: $e")
    }
}

Original enter image description here

Sergi Mansilla
  • 12,495
  • 10
  • 39
  • 48
  • You're writing meta with ```ImageIO``` as well as raw pixel data. ```getRGB``` would solve that – g00se Aug 29 '22 at 16:37
  • 1
    `ImageIO.read` returns a `BufferedImage`. What do you need the pixels for? If you need them, use `bImage.getRGB(0, 0, width, height, arr)` (don't use the TIFF-compressed data in `data`). Otherwise, just write `bImage` directly, using `ImageIO.write(bImage, "JPEG", File(...))`. – Harald K Aug 29 '22 at 19:04

1 Answers1

1

This line is not returning the RGB image data:

val data = bos.toByteArray()

it is returning the compressed stream of the image in tiff format, surely it is not the correct image.

To get the pixels, use Image.getPixel(), alternatively you can get the buffer of the image directly, but to this you need to know what is the underlying buffer type - this is broad topic.

Take a look at this answer, it should give you idea how to do it: convert a RGB image to grayscale Image reducing the memory in java

Krzysztof Cichocki
  • 6,294
  • 1
  • 16
  • 32
  • That made it click, thanks! I was taking the compressed data as the raw pixels. – Sergi Mansilla Aug 29 '22 at 20:47
  • It's not the fact of compression/not compression that's the problem - it's the fact that you're treating an image which contains metadata (e.g. file header, tags etc.) as merely a matrix of pixel data – g00se Aug 29 '22 at 21:54
  • When it comes to TIFF, two main compression options are available–they're known as LZW or ZIP – Krzysztof Cichocki Aug 29 '22 at 21:59