java - 如何在使用字节数组更改后将图像字节数组转换为位图

标签 java android arrays bitmap steganography

我正在尝试在 Android 中实现隐写术,并且我已经实现了对图像进行逐位编码的代码。

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;
}

但是在将数据编码到图像中后,我无法形成位图。

我已经在java中实现了相同的算法并且运行良好:

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;
}

有人可以帮我弄清楚为什么字节数组在 android 的情况下无效吗?

最佳答案

您从 JPEG 数据的 byte[] 开始。然后,您可以修改该数据,半随机地更改位,而不考虑 JPEG 数据格式。然后,您尝试解码修改后的byte[]。毫不奇怪,BitmapFactory 无法对其进行解码,因为它不再是有效的图像格式。

我最好的猜测是您认为 byte[] 是 ARGB 格式的原始像素。

如果是这种情况,则在 Bitmap 上使用 getPixel()setPixel() 等方法来修改像素,并跳过位图编码和解码步骤。

关于java - 如何在使用字节数组更改后将图像字节数组转换为位图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48913084/

相关文章:

java - 检查对象是否是类的实例(但不是其子类的实例)

android - 日历 View 突出显示错误的星期

android - 获取日历 ID

javascript - 如何让对象在数组中找到自己的索引?

javascript - 使用动态创建的 .addEventListener

java - 将字符串数组元素插入列表中

java - 在生产代码中,无法验证请求参数或格式时的日志级别是多少

android - 无法在Android Studio中导入项目

c - scanf("%number[^\n], array[N].struct) 的字符串长度

java - 访问 LinkedHashMap 中最后一个对象中的方法