Search code examples
javabmpsteganography

Extract appended data from BMP


I would like to extract appended data from a BMP image file.

In my function data stream of chosen BMP image is provided as an input. After the file type I read the file size and then I need to iterate over the rest of the stream. Additional data were appended to the BMP file therefore file size encoded in the image header is unchanged.

How can I get a value from the file size byte array which will determine how many bytes I will need to read until the end of original file? (I need to iterate for the right amount of bytes just to get before appended data)

private String getBMPAppendedData(DataInputStream in) {

        StringBuilder message = new StringBuilder();

        try {
            // Read the fileType : always 0x4d42 = "BM"
            in.readShort();
            // Read the file size
            byte[] fileSizeBytes = new byte[4];
            in.readFully(fileSizeBytes);

            // Read bytes in the loop 
            loop () {
            in.readByte();
            }

            // Read appended byte by byte if present
            boolean areSecretDataPresent = true;

            while (areSecretDataPresent) {
                try {

                    byte b = in.readByte();
                    message.append(String.format("%02X", b));

                } catch (Exception e) {

                    areSecretDataPresent = false;
                }
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }

        return message.toString();
    }

Solution

  • /**
     * Read an extra message, if it exists, from an InputStream containing a BMP image.
     *
     * @param is the InputStream to read from
     * @return the message found
     * @throws IOException if any exception other than EndOfFile is thrown after the BMP image
     */
    private static String readExtraMessage(final InputStream is) throws IOException {
        final DataInputStream s = new DataInputStream(is);
        final byte b = 0x42; // 'B'
        final byte m = 0x4d; // 'M'
        final byte sig1 = s.readByte();
        final byte sig2 = s.readByte();
        if (!(sig1 == b && sig2 == m)) {
            throw new IllegalArgumentException("not a BMP file");
        }
    
        final byte[] fileSizeBuffer = new byte[4];
        s.readFully(fileSizeBuffer);
        final int fileSize = ByteBuffer.wrap(fileSizeBuffer, 0, 4).order(ByteOrder.LITTLE_ENDIAN).getInt();
        int bytesToSkip = fileSize - 6; // 2 byte for the signature, 4 bytes for the filesize.
        while (bytesToSkip > 0) {
            bytesToSkip -= s.skipBytes(bytesToSkip);
        }
    
        final StringBuilder buf = new StringBuilder();
        while (true) {
            try {
                final byte x = s.readByte();
                buf.append((char) x);
            } catch (final EOFException e) {
                break;
            }
        }
    
        return buf.toString();
    }