Преобразование массива byte [] в объект BufferedImage - PullRequest
0 голосов
/ 19 октября 2019

Я взял изображение в объект BufferedImage. Теперь я преобразовал массив в байтовый массив. Я хотел изменить байтовые данные, а затем распечатать новое изображение. Это преобразование дает мой нулевой объект в BufferedImage. Также, пожалуйста, скажите мне, как изображение хранится в одномерном байтовом массиве, потому что, по моему мнению, его размер для изображения 3 * 3 должен быть около 9, но, к шоку, это: 672 байта

Пожалуйста, помогите мне.

Я пробовал гуглить. Видел чужой код.

import java.io.*;
import javax.imageio.ImageIO;
import java.awt.*;
import javax.swing.*;
import java.awt.image.*;
class SVisualizer{
    JFrame f;
    JLabel l;
    SVisualizer(){
        f=new JFrame("SVisualizer");
        f.setLayout(new FlowLayout());
        f.setLocationRelativeTo(null);
        f.setSize(590, 428);
        f.setResizable(false);
        f.setDefaultCloseOperation(f.EXIT_ON_CLOSE);    
    }
    public byte[] inputImage(){
        try{
        File file=new File("C:/Users/sanss/OneDrive/Desktop/1.jpg");
        BufferedImage bufferedImage = ImageIO.read(file);
        ByteArrayOutputStream baos=new ByteArrayOutputStream();
        ImageIO.write(bufferedImage, "jpg", baos);
        return baos.toByteArray();
        }
        catch(Exception e){
            System.out.println("Image cannot be processed!?");
        }
        return null;
    }
    public BufferedImage outputImage(byte[]data){
        try{
         ByteArrayInputStream bis = new ByteArrayInputStream(data);
         BufferedImage bImage = ImageIO.read(bis);
         return bImage;
        }
        catch(Exception e){
            System.out.println("Error while parsing array!?");
        }
        return null;
    }
    public int[] setWeight(int n){
        int[] data=new int[n];
        for(int i=0;i<n;i++)
            data[i]=i;
        return data;
    }
    public void setRandom(byte[] data, int[] weight){
        //back to front and front to back, simple randomisation
        int n=data.length;
        for(int i=0;i<n/2;i++){
            byte temp1=data[i];
            int temp2=weight[i];
            data[i]=data[n-1-i];
            weight[i]=data[n-1-i];
            data[n-i-1]=temp1;
            weight[n-i-1]=temp2;
        }
    }
    public void setImage(BufferedImage bImage){
        ImageIcon imageIcon=null;
        try{
        imageIcon=new ImageIcon(bImage);
        f.setContentPane(new JLabel(imageIcon));
        f.setVisible(true);
        }
        catch(Exception e){
            System.out.println("Error in setImage");
            System.out.println("BufferedImage: "+bImage);
            System.out.println("ImageIcon: "+imageIcon);
        }
    }
    public void printByteArray(byte[]data){
        for(int i=0;i<data.length;i++)
            System.out.println(data[i]+" ");
    }
    /*
    public void bubbleSort(byte[] data, int[] weight){
        int n=data.length;
        BufferedImage finalImage=outputImage(data);
        for(int i=0;i<n;i++){
            for(int j=0;j<n-1-i;j++){

            }
        }
    }*/
    public static void main(String args[]){
        SVisualizer ob=new SVisualizer();
        byte[] array=ob.inputImage();
        int[] weight=ob.setWeight(array.length);
        ob.setRandom(array, weight);
        BufferedImage oImage=ob.outputImage(array);
        ob.setImage(oImage);
        //ob.printByteArray(array);
        System.out.println(array.length);
    }
}

1 Ответ

1 голос
/ 19 октября 2019

Байты JPEG не являются пикселями. JPEG является сжатым (и обычно с потерями) форматом. Непосредственное изменение байтов приведет к повреждению сжатых данных, в результате чего будет получен несовместимый файл, который больше не является допустимым изображением JPEG.

Чтобы преобразовать пиксели изображения в байтовый массив, вам необходимо будет прочитать необработанные данные пикселей из BufferedImage. ,Для этого сначала нужно решить, что будет означать каждое значение байта. Обычный подход заключается в использовании четырех байтов для хранения каждого пикселя: один для красного компонента цвета пикселя, один для зеленого компонента, один для синего компонента и один для альфа-компонента (прозрачности). Обычно это сокращенное обозначение RGBA.

Возможны многие другие конфигурации. Например, если ваше изображение в градациях серого, вы можете просто сохранить значение серого каждого пикселя в одном байте.

Если мы предполагаем первый подход, вы можете использовать метод getRGB BufferedImage для извлечениязначения:

int width = bImage.getWidth();
int height = bImage.getHeight();

byte[] bytes = new byte[width * height * 4];
ByteBuffer buffer = ByteBuffer.wrap(bytes);
IntBuffer intBuffer = buffer.asIntBuffer();

int[] rowPixels = new int[width];
for (int y = 0; y < height; y++) {
    bImage.getRGB(0, y, width, 1, rowPixels, 0, width);
    intBuffer.put(rowPixels);
}

return bytes;

Вы можете использовать setRGB для преобразования байтов обратно в изображение:

ByteBuffer buffer = ByteBuffer.wrap(data);
IntBuffer intBuffer = buffer.asIntBuffer();

BufferedImage bImage = new BufferedImage(width, height,
    BufferedImage.TYPE_INT_ARGB);

int[] rowPixels = new int[width];
for (int y = 0; y < height; y++) {
    intBuffer.get(rowPixels);
    bImage.setRGB(0, y, width, 1, rowPixels, 0, width);
}

Что касается того, как одномерный массив содержит пиксели: формат изображения укажет как. Как правило, каждая строка пикселей находится в массиве сразу после предыдущей строки. Точное число байтов между началом каждой строки в массиве называется шагом сканирования.

...