2016-04-20 65 views
0

我與交換的圖像的色值玩耍交換顏色值後改變,但我似乎找到了一些我不很明白 - 我似乎不能找到一個很好的在谷歌上閱讀此事。我可以完成交換圖像的顏色,但與輸入文件的大小相比,它也會改變輸出文件的大小。文件大小是位圖

下面是一個測試類,我寫來測試事情,做什麼的,總結起來就是:

  1. 分配位圖到內存中。
  2. 使RGB值的陣列。
  3. 拆分陣列RGB值的成三個單獨的陣列(R,G和B)。
  4. 交換紅色所有的值(R [0] < - > R [1],R [2] < - >ř[3]等)
  5. 加入三個陣列並將其分配給RGB值的陣列。
  6. 複製回位圖。
  7. 釋放分配的內存。
  8. 導出文件。

守則,如下圖所示:

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 
+0

什麼格式是輸入和輸出文件? – Reti43

+0

輸入和輸出都是.png格式。我將位圖加載爲:'Bitmap bmp = new Bitmap(「../../ input.png」);'並將其導出爲'bmp.Save(「../../ output.png」) ;'@ Reti43 –

+1

如果您加載輸入文件並立即保存而不做修改,它會與原始文件大小相同嗎? – Reti43

回答

1

PNG用途(無損)壓縮。這意味着輸出文件的大小將取決於您提供的數據。壓縮利用了數據中的冗餘,並通過刪除它來實現更小的尺寸。由於相鄰像素是相關的,所以圖像傾向於具有很多冗餘,即它們具有相似的值。在你的情況下會發生什麼,你的洗牌會干擾圖像的自然圖案,從而減少像素相關性和縮小比例。所以,當涉及壓縮數據時,他們佔用更多空間。

如果您要洗牌所有組件,我不會感到驚訝,您會發現輸出尺寸比單獨洗牌紅色更大。

+0

雖然我只是洗牌紅色的組件,但我對你的輸入進行了一些測試,它似乎是答案。感謝您抽出時間回答我的問題。 –

+0

@MikkelJarlund啊,是的,我的錯。有一段時間我記得它好像你已經切換了所有的組件。在這種情況下,我預計這個規模會進一步增長。我編輯了答案以正確反映。順便說一下,如果答案解決了您的問題,您可以選擇[標記爲已接受](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) 。 – Reti43

+0

完成並再次感謝你。我剛剛進入C#開發(4個月),這是我的第一個'大'項目,所以我仍然拼命想把它全部弄清楚。希望我能像你一樣,在我有點經驗的幾年內傳授我的知識。 –

0

您的阿爾法檢查的圖像,沒有什麼東西被保存。 PNG默認會保存alpha.Try這樣的:

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

+0

這就是爲什麼我問他是否加載並保存輸入文件而不做任何修改,而不管輸出文件是否會改變大小。這是爲了說明編碼器會嘗試包含原始圖像所具有的更多信息的情況。然而,OP表示他沒有注意到這種差異,所以我預計它的尺寸差異將歸因於他的像素修改。 – Reti43