Byte validation through an image bit array

Asked

Viewed 325 times

3

I am trying to validate an incoming image in an FTP folder. The images start with the bytes "FFD8" and end with the sequence "FFD9" so that there is the possibility to perform the check.

I’m getting the picture on BufferedImage and converting to an array of bytes, however, when access to the initial positions of this array never corresponds to the value of FFD8, I receive values like 001F 0019. I performed the verification of these same files in editors like sublimetext and some hexdumps and in them the initial and final bytes correspond with the correct value "FFD8" (Initial) and "FFD9" (Final). In this little bit of code I’m concatenating everything into one StringBuilder. What could I be doing wrong?

void startProcessBloco(){
    int qtdBloco = 0;
    File fList[] = diretorio.listFiles();
     for ( int i = 0; i < fList.length; i++ ){
         //Validação verificando se o vetor não é nulo
         if(fList.length > i + 3){
             if(fList[i].getName().contains("_1") && fList[i+3].getName().contains("_4")){

                 try {
                        File imagemFisica = new File(dir+fList[i].getName());
                        BufferedImage imagemEmBuffer = ImageIO.read(imagemFisica);
                        byte[] imagemEmBytes = bloco.extractBytes(imagemEmBuffer);
                        bloco.getImagens().add(imagemEmBuffer);

                        StringBuilder sb = new StringBuilder();
                        for (byte b : imagemEmBytes) {
                            sb.append(String.format("%04X ", b));
                        }
                        System.out.println(sb.toString());

                        ImageIO.write(imagemEmBuffer, "jpg",
                                new File("D:\\testesBlocoFtp\\recebeImg\\" + fList[i].getName()));

                    } catch (IOException e) {
                        e.printStackTrace();
                    }
             }
         }
     }
     System.out.println(qtdBloco);
}

2 answers

2

In your code there’s this:

if(fList[i].getName().contains("_1") && fList[i+3].getName().contains("_4")){

This fList[i] and this fList[i+3] tell me that you expect the elements in the array to be in a deteminated order. However Javadocs of the listFiles method() is written:

There is no Guarantee that the name strings in the Resulting array will appear in any specific order; they are not, in particular, Guaranteed to appear in Alphabetical order.

What translating into Portuguese is:

There is no guarantee that the strings with the names in the resulting array will appear in any specific order; they are in particular not guaranteed to appear in alphabetical order.

Also, bytes in Java go from -128 to 127, differently than most would expect it to be from 0 to 255. And you’re using this:

String.format("%04X ", b)

Let’s see what this prints with a few bytes:

System.out.println(String.format("%04X ", (byte) -128));
System.out.println(String.format("%04X ", (byte) -127));
System.out.println(String.format("%04X ", (byte) -40));
System.out.println(String.format("%04X ", (byte) -39));
System.out.println(String.format("%04X ", (byte) -2));
System.out.println(String.format("%04X ", (byte) -1));
System.out.println(String.format("%04X ", (byte) 0));
System.out.println(String.format("%04X ", (byte) 1));
System.out.println(String.format("%04X ", (byte) 31));
System.out.println(String.format("%04X ", (byte) 25));
System.out.println(String.format("%04X ", (byte) 126));
System.out.println(String.format("%04X ", (byte) 127));
System.out.println(String.format("%04X ", (byte) 128));
System.out.println(String.format("%04X ", (byte) 129));
System.out.println(String.format("%04X ", (byte) 216));
System.out.println(String.format("%04X ", (byte) 217));
System.out.println(String.format("%04X ", (byte) 254));
System.out.println(String.format("%04X ", (byte) 255));

Here’s the way out:

0080 
0081 
00D8 
00D9 
00FE 
00FF 
0000 
0001 
001F 
0019 
007E 
007F 
0080 
0081 
00D8 
00D9 
00FE 
00FF 

Well, Using "%04X ", you will ALWAYS see the first two digits being zeros. Maybe "%02 " makes more sense. The 001F corresponds to 31, the 0019 corresponds to 25. O 00D8 corresponds to -40 (or 216) and 00D9 corresponds to -39 (or 217). Note the following:

System.out.println(String.format("%04X ", (short) -40));
System.out.println(String.format("%04X ", (short) -39));

Here’s the way out:

FFD8
FFD9

They are the same values -40 and -39, but represented as short instead of byte.

I know this still doesn’t solve your problem completely, but it should help you.

  • It helped a lot, from his reply I started thinking in a different direction and after researching a little more, I found two libraries that fell like a glove .

0


I ended up solving my problem using the following libraries:

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.io.IOUtils;

With Commons.io.Ioutils the transformation of Inputstream, which in the previous code was received through a File class object became much easier:

byte[] imagemEmBytes = IOUtils.toByteArray(imagemFisica);

And with Commons.codec.Binary.Hex the transformation of the byte array into a string in Hex returned the correct value in a string with the hexa code of the image. Then just performed the validation:

if (Hex.encodeHexString(imagemEmBytes).startsWith("ffd8") &&
    Hex.encodeHexString(imagemEmBytes).endsWith("ffd9")) {
    //Minha imagem foi validada, faço oque quiser com ela aqui.
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.