簡體   English   中英

將灰度BMP寫入Memorystream的ZIP文件

[英]Write grayscale BMP to ZIP file from Memorystream

我正在嘗試測試單個圖像或壓縮包是否更快。 我的方法是創建一個0到255之間的值(8位圖像)的隨機字節數組,並從中形成一個Bitmap,使用Bitmap.Save重復寫入。 通過這種方式,我可以將PixelFormat設置為Format8bppIndexed,它可以提供灰度圖像:

// Random number Generator
Random rnd = new Random();

// Create a single image
int Width = 640;
int Height = 512;
var b = new Bitmap(Width, Height, PixelFormat.Format8bppIndexed);
ColorPalette ncp = b.Palette;
for (int i = 0; i < 256; i++)
    ncp.Entries[i] = Color.FromArgb(255, i, i, i);
b.Palette = ncp;

var BoundsRect = new Rectangle(0, 0, Width, Height);
BitmapData bmpData = b.LockBits(BoundsRect,
                ImageLockMode.WriteOnly,
                b.PixelFormat);
IntPtr ptr = bmpData.Scan0;
int bytes = bmpData.Stride * b.Height;
var rgbValues = new byte[bytes];

// fill in rgbValues, e.g. with a for loop over an input array
rnd.NextBytes(rgbValues);

Marshal.Copy(rgbValues, 0, ptr, bytes);
b.UnlockBits(bmpData);

// copy image to a list of ~1000
List<Bitmap> bmps = new List<Bitmap>();
for (int i = 0; i < 500; i++)
    bmps.Add(new Bitmap(b));

// Write to individual files
DateTime t0=DateTime.Now;
for (int i=0;i<bmps.Count;i++)
    b.Save(@"C:\Temp\DiskTransferTest\IndividualImages\" + i.ToString() + ".bmp");
DateTime t1=DateTime.Now;
Console.WriteLine("Time to write individually: " + (t1-t0).ToString());

之后,我嘗試將它們全部壓縮成一個ZIP文件並使用DotNetZip保存。 這是有效的,但我得到的是彩色圖像而不是灰度圖像,所以文件大小要大得多。

// Create memorystreams from bitmap to pass to DotNetZip
List<MemoryStream> mss = new List<MemoryStream>();
for (int i = 0; i < bmps.Count; i++)
{
    mss.Add(new MemoryStream());
    bmps[i].Save(mss[i], ImageFormat.Bmp);
    mss[i].Seek(0, SeekOrigin.Begin);
}

// Compress and write
t0 = DateTime.Now;
using (ZipFile zipfile = new ZipFile())
{
    zipfile.CompressionLevel = 0;
    int i=0;
    foreach (MemoryStream ms in mss)
        {
         string pictureName = i.ToString() + ".bmp";
         zipfile.AddEntry(pictureName,ms);
         i++;
        }           
    zipfile.Save(@"C:\Temp\DiskTransferTest\zipped.zip");
}
t1 = DateTime.Now;
Console.WriteLine("Time to write compressed: " + (t1 - t0).ToString());

有關如何通過MemoryStream將zip格式寫入zip的任何建議?

據我所知,使用Bitmap類創建真正的灰度圖像是不可能的。 您必須將Bitmap.Palette屬性從當前ColorPaletteGrayscalePalette ,該GrayscalePalette每種顏色只存儲一個字節,而不是每個ARGB顏色所需的四個字節。 該框架不包含任何此類, ColorPalette不繼承基類或實現接口,並且它也是密封的,因此您也不能繼承該類。

另一方面,檢查位圖文件格式規范我發現無法保存真正的灰度位圖圖像(使用256字節顏色表)。 在Photoshop CS6中保存8位灰度圖像然后再次打開它會顯示它被保存為8位顏色索引圖像(盡管R = G = B,適用於調色板中的所有顏色)。

問題是您的新位圖不是8bpp位圖。 考慮你的代碼:

// copy image to a list of ~1000
List<Bitmap> bmps = new List<Bitmap>();
for (int i = 0; i < 500; i++)
    bmps.Add(new Bitmap(b));

// Write to individual files
DateTime t0=DateTime.Now;
for (int i=0;i<bmps.Count;i++)
    b.Save(@"C:\Temp\DiskTransferTest\IndividualImages\" + i.ToString() + ".bmp");

位圖b是8bpp位圖。 你正在把它寫到文件中。 但是如果你檢查bmps[0]我認為你會發現PixelFormat是32bpp。 至少,當我執行此代碼時會發生這種情況:

var bmp = new Bitmap(640, 480, PixelFormat.Format8bppIndexed);
Console.WriteLine(bmp.PixelFormat); // 8 bpp
var bmp2 = new Bitmap(bmp);
Console.WriteLine(bmp2.PixelFormat); // 32 bpp

在將位圖寫入內存流的代碼中,您正在訪問bmps[i] ,而不是8bpp圖像, b ,就像寫入文件時一樣。

您需要創建列表位圖,設置其屬性,然后復制b 您無法使用new Bitmap(b)構造函數調用復制位圖及其屬性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM