简体   繁体   中英

How to convert image byte array into a bitmap after altering with the byte array

I am trying to implement Steganography in Android and I have implemented the code to encode the image bit by bit.

private Bitmap add_text(Bitmap image, String text)
{
    //convert all items to byte arrays: image, message, message length
    byte img[]  = get_byte_data(image);
    byte msg[] = text.getBytes();
    byte len[]   = bit_conversion(msg.length);
    displaybit(img, "Start");

    try
    {
        encode_text(img, len,  0); //0 first positiong
        encode_text(img, msg, 32); //4 bytes of space for length: 4bytes*8bit = 32 bits

        return BitmapFactory.decodeByteArray(img, 0, img.length);
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
    return image;
}

private byte[] get_byte_data(Bitmap image)
{
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    image.compress(Bitmap.CompressFormat.JPEG, 100, stream);

    return stream.toByteArray();
}

private byte[] bit_conversion(int i)
{
    //originally integers (ints) cast into bytes
    //byte byte7 = (byte)((i & 0xFF00000000000000L) >>> 56);
    //byte byte6 = (byte)((i & 0x00FF000000000000L) >>> 48);
    //byte byte5 = (byte)((i & 0x0000FF0000000000L) >>> 40);
    //byte byte4 = (byte)((i & 0x000000FF00000000L) >>> 32);

    //only using 4 bytes
    byte byte3 = (byte)((i & 0xFF000000) >>> 24); //0
    byte byte2 = (byte)((i & 0x00FF0000) >>> 16); //0
    byte byte1 = (byte)((i & 0x0000FF00) >>> 8 ); //0
    byte byte0 = (byte)((i & 0x000000FF)       );
    //{0,0,0,byte0} is equivalent, since all shifts >=8 will be 0
    return(new byte[]{byte3,byte2,byte1,byte0});
}

private byte[] encode_text(byte[] image, byte[] addition, int offset)
{
    //check that the data + offset will fit in the image
    if(addition.length + offset > image.length)
    {
        throw new IllegalArgumentException("File not long enough!");
    }
    //loop through each addition byte
    for(int i=0; i<addition.length; ++i)
    {
        //loop through the 8 bits of each byte
        int add = addition[i]; //0
        for(int bit=7; bit>=0; --bit, ++offset) //ensure the new offset value carries on through both loops
        {
            //assign an integer to b, shifted by bit spaces AND 1
            //a single bit of the current byte
            int b = (add >>> bit) & 1;
            //assign the bit by taking: [(previous byte value) AND 0xfe] OR bit to add
            //changes the last bit of the byte in the image to be the bit of addition
            image[offset] = (byte)((image[offset] & 0xFE) | b );
        }
    }
    return image;
}

But I am not able to form a bitmap after encoding the data into the image.

I have implemented the same algorithm in java and it works fine:

private BufferedImage add_text(BufferedImage image, String text)
{
    //convert all items to byte arrays: image, message, message length
    byte img[]  = get_byte_data(image);
    byte msg[] = text.getBytes();
    byte len[]   = bit_conversion(msg.length);
    try
    {
        encode_text(img, len,  0); //0 first positiong
        encode_text(img, msg, 32); //4 bytes of space for length: 4bytes*8bit = 32 bits
    }
    catch(Exception e)
    {
        JOptionPane.showMessageDialog(null, 
"Target File cannot hold message!", "Error",JOptionPane.ERROR_MESSAGE);
    }
    return image;
}

So could some one please help me figure out why the byte array is invalid in the case of android.

You start with a byte[] of JPEG data. You then modify that data, changing bits semi-randomly, without regard to the JPEG data format. You then attempt to decode the modified byte[] . Not surprisingly, BitmapFactory cannot decode it, as it is no longer a valid image format.

My best guess is that you think that the byte[] is raw pixels in ARGB format.

If that is the case, then use methods like getPixel() and setPixel() on Bitmap to modify the pixels, and skip the bitmap encoding and decoding steps.

I was finally able to figure it out, as mentioned above in the comment the solution was solving it pixel by pixel. So I took a pixel and put the data in its rgb value bit by bit. So this is the code:

private Bitmap add_text(Bitmap image, String text, File tempFile) {
    //convert all items to byte arrays: image, message, message length
    byte msg[] = text.getBytes();
    byte len[] = bit_conversion(msg.length);

    try {

        return encodeTextRGB(image, len, msg, tempFile);

    } catch (Exception e) {
        e.printStackTrace();
    }
    return image;
}

private byte[] bit_conversion(int i) {
    //originally integers (ints) cast into bytes
    //byte byte7 = (byte)((i & 0xFF00000000000000L) >>> 56);
    //byte byte6 = (byte)((i & 0x00FF000000000000L) >>> 48);
    //byte byte5 = (byte)((i & 0x0000FF0000000000L) >>> 40);
    //byte byte4 = (byte)((i & 0x000000FF00000000L) >>> 32);

    //only using 4 bytes
    byte byte3 = (byte) ((i & 0xFF000000) >>> 24); //0
    byte byte2 = (byte) ((i & 0x00FF0000) >>> 16); //0
    byte byte1 = (byte) ((i & 0x0000FF00) >>> 8); //0
    byte byte0 = (byte) ((i & 0x000000FF));
    //{0,0,0,byte0} is equivalent, since all shifts >=8 will be 0
    return (new byte[]{byte3, byte2, byte1, byte0});
}

public Bitmap encodeTextRGB(Bitmap buffer, byte[] len, byte[] data, File tempFile) {

    pixelRow = 0;
    pixelCol = 0;

    byte[] overhead = len;

    int bitCount = 0;
    int iteration = 0;

    while (iteration++ < 2) {
        for (int i = 0; i < overhead.length; i++) {
            byte currentByte = overhead[i];
            System.out.println("add: " + currentByte);
            for (int j = 7; j >= 0; j--) {
                int bit = (currentByte & (0x1 << j)) >> j;
                bit = bit & 0x1;
                System.out.println("Bit: " + bit);
                if (bitCount % 3 == 0) {
                    int red;
                    if (bit == 0) {
                        red = Color.red(buffer.getPixel(pixelCol, pixelRow)) & 0xFE;
                    } else {
                        red = Color.red(buffer.getPixel(pixelCol, pixelRow)) | 0x1;
                    }
                    buffer.setPixel(pixelCol, pixelRow, Color.argb(
                            Color.alpha(buffer.getPixel(pixelCol, pixelRow)), red,
                            Color.green(buffer.getPixel(pixelCol, pixelRow)),
                            Color.blue(buffer.getPixel(pixelCol, pixelRow))));
                } else if (bitCount % 3 == 1) {
                    int blue;
                    if (bit == 0) {
                        blue = Color.blue(buffer.getPixel(pixelCol, pixelRow)) & 0xFE;
                    } else {
                        blue = Color.blue(buffer.getPixel(pixelCol, pixelRow)) | 0x1;
                    }
                    buffer.setPixel(pixelCol, pixelRow, Color.argb(
                            Color.alpha(buffer.getPixel(pixelCol, pixelRow)),
                            Color.red(buffer.getPixel(pixelCol, pixelRow)),
                            Color.green(buffer.getPixel(pixelCol, pixelRow)), blue));
                } else {
                    int green;
                    if (bit == 0) {
                        green = Color.green(buffer.getPixel(pixelCol, pixelRow)) & 0xFE;
                    } else {
                        green = Color.green(buffer.getPixel(pixelCol, pixelRow)) | 0x1;
                    }
                    buffer.setPixel(pixelCol, pixelRow, Color.argb(
                            Color.alpha(buffer.getPixel(pixelCol, pixelRow)),
                            Color.red(buffer.getPixel(pixelCol, pixelRow)), green,
                            Color.blue(buffer.getPixel(pixelCol, pixelRow))));
                    incrementPixel(buffer.getWidth());
                }
                bitCount++;
            }
        }

        overhead = data;
    }
    FileOutputStream out = null;
    try {
        out = new FileOutputStream(tempFile);
        buffer.compress(Bitmap.CompressFormat.PNG, 100, out);
        out.flush();
        out.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    incrementPixel(buffer.getWidth());
    return buffer;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM