Прочетете .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[], но не се получи. байт fileContent[] = нов байт[(int)inputFile.length()]; for(int i = 0; i ‹ (int)inputFile.length(); i++){ fileContent[i] = (байт) inputStream.read(); } for(int i = 0; i ‹ (int)inputFile.length(); i++){ outputStream.write(fileContent[i]); } outputStream.flush(); outputStream.close();   -  person pkthapa    schedule 05.02.2013
comment
1) Това е известно като стеганография. Добавих етикета към публикацията. 2) Обикновено не се постига чрез промяна на конкретен байт в File, както изглежда, че правите, а вместо това на „данните“ на самото изображение или звук. В този случай ще прочетете fie в 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