0

個々の画像を書き込むのが速いのか、バンドルを圧縮するのが速いのかをテストしようとしています。私のアプローチは、0〜255(8ビットイメージ)の値のランダムなバイト配列を作成し、そこからビットマップを作成し、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());

その後、DotNetZipを使用して、それらすべてを1つのZIPファイルに圧縮して保存します。これは機能しますが、グレースケールではなくカラー画像を取得するため、ファイルサイズははるかに大きくなります。

// 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にグレースケールを書き込む方法に関する提案はありますか?

4

2 に答える 2

1

私の知る限り、このクラスを使用して真のグレースケール画像を作成することはできません。プロパティを現在から、ARGBカラーごとに必要な4バイトではなく、カラーごとに1バイトしか格納しないプロパティBitmapに交換する必要があります。フレームワークにはそのようなクラスは含まれていません。基本クラスを継承したり、インターフェイスを実装したりすることもありません。また、クラスから継承できないように封印されています。Bitmap.PaletteColorPaletteGrayscalePaletteColorPalette

一方、ビットマップファイル形式の仕様を確認すると、(256バイトのカラーテーブルを使用して)真のグレースケールビットマップイメージを保存する方法がないことがわかります。Photoshop CS6で8ビットのグレースケール画像を保存してからもう一度開くと、8ビットのカラーインデックス付き画像として保存されたことがわかります(ただし、パレットのすべての色でR = G = Bです)。

于 2013-03-14T13:18:07.873 に答える
1

問題は、新しいビットマップが 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 ビットマップです。ファイルに書き込んでいます。しかし、調べてみると、が 32bppbmps[0]であることがわかると思います。PixelFormat少なくとも、このコードを実行するとこうなります。

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

リスト ビットマップを作成し、それらのプロパティを設定して、コピーする必要がありますbnew Bitmap(b)コンストラクター呼び出しを使用して、ビットマップとそのプロパティを複製することはできません。

于 2013-03-14T13:59:36.487 に答える