Прочитайте изображение .bmp и вычтите 10 из 10-го байта изображения и заново создайте изображение на Java.

Я создаю приложение, которое будет считывать байт/пиксель/данные изображения из изображения .bmp и сохранять его в массиве byte/char/int/etc.

Теперь из этого массива я хочу вычесть 10 (в десятичной форме) из данных, хранящихся в 10-м индексе массива.

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

Это фрагмент кода, который я пытался сделать.

В этом коде я не вычитаю 10 из 10-го индекса массива.

public class Test1 {

    public static void main(String[] args) throws IOException{
        File inputFile = new File("d://test.bmp");
        FileReader inputStream = new FileReader("d://test.bmp");
        FileOutputStream outputStream = new FileOutputStream("d://test1.bmp");
        /*
         * Create byte array large enough to hold the content of the file.
         * Use File.length to determine size of the file in bytes.
         */
        char fileContent[] = new char[(int)inputFile.length()];


        for(int i = 0; i < (int)inputFile.length(); i++){
            fileContent[i] = (char) inputStream.read();
        }

        for(int i = 0; i < (int)inputFile.length(); i++){
            outputStream.write(fileContent[i]);
        }
    }
}

person pkthapa    schedule 05.02.2013    source источник
comment
Почему вы используете char[]? У вас нет текстовых данных. Вместо этого используйте byte[].   -  person Jon Skeet    schedule 05.02.2013
comment
Я хочу вычесть 10 (в десятичной форме) из данных, хранящихся в 10-м индексе массива. Почему именно?   -  person Andrew Thompson    schedule 05.02.2013
comment
Я хочу скрыть некоторую информацию на этом изображении, а затем получить ту же информацию. Я также пробовал использовать char[], это не сработало. byte fileContent[] = новый байт[(int)inputFile.length()]; for(int i = 0; i ‹ (int) inputFile.length(); i++){ fileContent[i] = (byte) inputStream.read(); } for(int i = 0; i ‹ (int) inputFile.length(); i++){ outputStream.write(fileContent[i]); } outputStream.flush(); выходной поток.close();   -  person pkthapa    schedule 05.02.2013
comment
1) Это широко известно как стеганография. Я добавил тег к сообщению. 2) Обычно это достигается не путем изменения определенного байта в File, как вы, кажется, делаете, а вместо этого «данных» самого изображения или звука. В этом случае вы должны прочитать файл в BufferedImage, манипулировать самим изображением и записать его обратно в файл. 3) Добавьте @JonSkeet (или кого-то еще), чтобы уведомить их о новом комментарии. 4) Код в комментариях не читается. Вместо этого отредактируйте его в вопросе и используйте форматирование кода.   -  person Andrew Thompson    schedule 05.02.2013


Ответы (3)


Вместо char[] используйте byte[]

Вот модифицированная версия, если ваш код работает:

public class Test {

public static void main(String[] args) throws IOException {
    File inputFile = new File("someinputfile.bmp");
    FileOutputStream outputStream = new FileOutputStream("outputfile.bmp");
    /*
     * Create byte array large enough to hold the content of the file.
     * Use File.length to determine size of the file in bytes.
     */
    byte fileContent[] = new byte[(int)inputFile.length()];


    new FileInputStream(inputFile).read(fileContent);

    for(int i = 0; i < (int)inputFile.length(); i++){
        outputStream.write(fileContent[i]);
    }

    outputStream.close();
 }
}
person NickJ    schedule 05.02.2013
comment
Он все еще не работает даже после использования массива byte[] вместо char[] - person pkthapa; 05.02.2013
comment
Вы также не забыли закрыть OutputStream? - person NickJ; 05.02.2013

Чтобы ваш существующий код работал, вы должны заменить FileReader на FileInputStream. Согласно javadoc FileReader:

FileReader предназначен для чтения потоков символов. Для чтения потоков необработанных байтов рассмотрите возможность использования FileInputStream.

Изменение образца, как показано ниже

  public static void main(String[] args) throws IOException
 {
File inputFile = new File("d://test.bmp");
FileInputStream inputStream = new FileInputStream("d://test.bmp");
FileOutputStream outputStream = new FileOutputStream("d://test1.bmp");
/*
 * Create byte array large enough to hold the content of the file.
 * Use File.length to determine size of the file in bytes.
 */
byte fileContent[] = new byte[(int)inputFile.length()];

for(int i = 0; i < (int)inputFile.length(); i++){
    fileContent[i] =  (byte) inputStream.read();
}

inputStream.close();
for(int i = 0; i < (int)inputFile.length(); i++){
    outputStream.write(fileContent[i]);
}

outputStream.flush();
outputStream.close();

}

Эта работа для меня, чтобы создать копию исходного изображения.

Хотя, как упоминалось в комментариях выше, это, вероятно, неправильный подход к тому, чего вы пытаетесь достичь.

person David Hodgson    schedule 05.02.2013

Другие указали вам на ошибки в вашем коде (в основном с использованием char вместо byte), однако, даже если вы это исправите, вы, вероятно, получите незагружаемое изображение, если измените значение 10-го байта в файле.

Это связано с тем, что файл изображения .bmp начинается с заголовка, содержащего информацию о файле (глубина цвета, размеры, ... см. Формат файла BMP) перед любыми фактическими данными изображения. В частности, 10-й байт является частью 4-байтового целого числа, в котором хранится смещение фактических данных изображения (массив пикселей). Таким образом, вычитание 10 из этого значения, вероятно, приведет к тому, что смещение будет указывать на неправильную точку в файле, и ваш загрузчик изображений, выполняющий проверку границ, вероятно, сочтет это недействительным.

Что вы действительно хотите сделать, так это загрузить изображение как изображение и напрямую управлять значениями пикселей. Что-то подобное:

BufferedImage originalImage = ImageIO.read(new File("d://test.bmp"));
int rgb = originalImage.getRGB(10, 0);
originalImage.setRGB(rgb >= 10 ? rgb - 10 : 0);
ImageIO.write(originalImage, "bmp", new File("d://test1.bmp"));
person Sylvain Defresne    schedule 05.02.2013