在位图中交换颜色值后,文件大小会发生变化

时间:2016-04-20 21:24:35

标签: c# bitmap steganography

我正在玩交换图像的颜色值,但我似乎找到了一些我不太了解的东西 - 而且我似乎无法在谷歌上找到关于这个问题的好读物。我可以完成交换图像的颜色,但它也会改变输出文件的大小,与输入文件的大小相比。

以下是我为测试此事而编写的测试类,以及它的作用,总结如下:

  1. 将位图分配给内存。
  2. 制作一组RGB值。
  3. 将RGB值数组拆分为三个独立的数组(r,g和b)。
  4. 以红色交换所有值(r [0]< - > r [1],r [2]< - > r [3]等。)
  5. 加入三个数组并分配给RGB值数组。
  6. 复制回位图。
  7. 释放分配的内存。
  8. 导出文件。
  9. 代码如下所示:

    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Runtime.InteropServices;
    
    namespace GraphTheory
    {
        class Test
        {
            public Test(Bitmap bmp)
            {
    
                #region Assign bitmap to memory
    
                // Rectangle to hold the bmp.
                Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
    
                // Lock the bitmap to the rectangle / system memory.
                BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat);
    
                // Get the adress of the first line.
                IntPtr ptr = bmpData.Scan0;
    
                // Declare an array to hold the bytes of the bitmap.
                int bytes = Math.Abs(bmpData.Stride) * bmp.Height;
                byte[] rgb = new byte[bytes];
    
                // Copy the RGB values of the bitmap into the array.
                Marshal.Copy(ptr, rgb, 0, bytes);
    
                #endregion
    
                #region Split rgb array into three arrays
    
                // Number of colors in the image.
                int colors = bytes / 3;
    
                // Declare three arrays to hold the RGB values of the bitmap.
                byte[] r = new byte[colors];
                byte[] g = new byte[colors];
                byte[] b = new byte[colors];
    
                // Set starting pos of color index.
                int colorIndex = 0;
    
                // Split the array of RGB values into three seperate arrays.
                for (int i = 0; i < rgb.Length; i += 3)
                {
                    int j = i + 1, k = i + 2;
    
                    r[colorIndex] = rgb[k];
                    g[colorIndex] = rgb[j];
                    b[colorIndex] = rgb[i];
    
                    colorIndex++;
                }
    
                #endregion
    
                #region Hide data in the colors of the bitmap
    
                for (int i = 0; i < colors; i += 2)
                {
                    switchBits(ref r[i], ref r[i + 1]);
                }
                #endregion
    
                #region Join the three arrays into one rgb array
    
                // Reset color index.
                colorIndex = 0;
    
                // Replace the values of the rgb array with the values of the r, g and b arrays.
                for (int i = 0; i < rgb.Length; i += 3)
                {
                    int j = i + 1, k = i + 2;
    
                    rgb[k] = r[colorIndex];
                    rgb[j] = g[colorIndex];
                    rgb[i] = b[colorIndex];
    
                    colorIndex++;
                }
    
                #endregion
    
                #region Free bitmap from memory and save to file
    
                // Copy the RGB values back to the bitmap
                Marshal.Copy(rgb, 0, ptr, bytes);
    
                // Unlock the bits.
                bmp.UnlockBits(bmpData);
    
                // Export the image.
                bmp.Save("../../output.png");
    
                #endregion
            }
    
            private void switchBits(ref byte bit1, ref byte bit2)
            {
                byte tmp = bit1;
                bit1 = bit2;
                bit2 = tmp;
            }
        }
    }
    

    我根本不明白为什么会改变位图的图像大小,因为我没有替换任何颜色值,只是重新排列它们。

    输入文件的大小:[884 KB]

    输出文件的大小:[1335 KB]

    没有图片不包含Alpha通道:

    Image.IsAlphaPixelFormat(image.PixelFormat) == false
    

2 个答案:

答案 0 :(得分:1)

PNG使用(无损)压缩。这意味着输出文件的大小取决于您提供的数据。压缩利用数据中的冗余并通过删除它,可以实现更小的尺寸。图像倾向于具有大量冗余,因为相邻像素是相关的,即它们具有相似的值。在你的情况下发生的事情是你的洗牌有点干扰图像的自然图案,从而减少像素相关性和减少。因此,在压缩数据时,它们会占用更多空间。

如果你要对所有组件进行洗牌,我不会感到惊讶,你会发现输出大小的增长甚至超过仅仅改变红色的大小。

答案 1 :(得分:0)

您对alpha的检查是针对图片的,而不是保存的内容。默认情况下,PNG将保存alpha。请尝试:

WPF - How do I save a PNG without any alpha channel?