byte配列を8bitグレースケール画像で保存する際の表示のずれを無くしたい
Visual studio 2019のWindowsフォームアプリケーション(.NET framework)を使用してこちらのサイト(https://symfoware.blog.fc2.com/blog-entry-2195.html)を参考に8bitグレースケール画像を作成しようとしておりますが、画像サイズの部分の値を変更するとピクセル数全体に色が割り当てられずに抜けがある画像が作成されてしまいます。割り当てられる領域に限界があることを考慮し、コードよりも大きいサイズでは(例500×300ピクセル)抜けがなくすべてのピクセルに指定した色が割り当てられていることを確認しました。
色を割り当てたい具体的な画像サイズとしては330×330ピクセルです。考えられる原因および解決策ございましたら是非ご教授願いたく思います。
よろしくお願いいたします。
発生している問題・エラーメッセージ
画像の下から1行目全てと2行9列目以降で指定した色(灰色)が割り当てられず黒色となっています。
該当のソースコード
using System; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices;//追加 namespace image { public partial class Form1:Form { public Form1() { int Gwidth = 330; int Gheight = 330; byte[] Gdata = new byte[Gwidth * Gheight]; for(int h = 0; h < Gheight; h++) { for (int w = 0; w < Gwidth; w++) { data[h * Gwidth + w] = (byte)225; } } Bitmap Gimg = new Bitmap(Gwidth, Gheight, PixelFormat.Format8bppIndexed); ColorPalette pal = Gimg.Palette; for (int i = 0; i < 256; ++i) { pal.Entries[i] = Color.FromArgb(i, i, i); } img.Palette = pal; BitmapData bmpdata = Gimg.LockBits( new Rectangle(0, 0, Gwidth, Gheight), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed ); Marshal.Copy(Gdata, 0, bmpdata.Scan0, Gdata.Length); Gimg.UnlockBits(bmpdata); Gimg.Save(@"D:¥sources¥new3.jpg"); } } } //以下変更後 public Form1() { ////byte配列をグレースケール画像で保存する//// Bitmap empty = new Bitmap(330, 330);//空の画像(入力) int Gwidth = 330; int Gheight = 330; byte[] Gdata = new byte[Gwidth*Gheight]; for (int h = 0; h < Gheight; h++) { for(int w =0; w < Gwidth; w++) { Gdata[h *Gwidth+ w] = (byte)numbers[h*Gwidth+w]; } } unsafe { //出力ビットマップの領域確保 Bitmap Gimg = new Bitmap(empty.Width, empty.Height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed); //出力ビットマップをシステムメモリにロック BitmapData dataRgb = empty.LockBits(new Rectangle(0, 0, empty.Width, empty.Height),ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb); BitmapData bmpdata = Gimg.LockBits(new Rectangle(0, 0, Gimg.Width, Gimg.Height), ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed); byte* datas24bppRgb = (byte*)dataRgb.Scan0; byte* datas8bppGray = (byte*)bmpdata.Scan0; int lineIn = empty.Width * 3; int lineInNew = (lineIn % 4 != 0) ? ((lineIn / 4 + 1) * 4) : lineIn; int lineInDiff = lineInNew - lineIn; int offsetIn = 0; int lineOut = empty.Width; int lineOutNew = (lineOut % 4 != 0) ? ((lineOut / 4 + 1) * 4) : lineOut; int lineOutDiff = lineOutNew - lineOut; int offsetOut = 0; // ポインタを介して、ピクセル毎にグレースケール化 for (int y = 0; y < empty.Height; y++) { for (int x = 0; x < empty.Width; x++) { // 4バイト境界の考慮 datas8bppGray[y * empty.Width + x + offsetOut] = (byte)( ((int)(datas24bppRgb[y * empty.Width * 3 + x * 3 + offsetIn]) + (int)(datas24bppRgb[y * empty.Width * 3 + x * 3 + offsetIn + 1]) + (int)(datas24bppRgb[y * empty.Width * 3 + x * 3 + offsetIn + 2])) / 3); } // 4バイト境界の考慮 offsetIn += lineInDiff; offsetOut += lineOutDiff; } //パレット情報の設定 ColorPalette pal = Gimg.Palette; for (int i = 0; i < 256; ++i) { pal.Entries[i] = System.Drawing.Color.FromArgb(i, i, i); } Gimg.Palette = pal; Marshal.Copy(Gdata, 0, bmpdata.Scan0, Gdata.Length); //出力ビットマップのロック解除 empty.UnlockBits(dataRgb); Gimg.UnlockBits(bmpdata); Gimg.Save(@"D:\sources\new3.jpg"); } ////byte配列をグレースケール画像で保存する//// }
試したこと
333×333、330×330ピクセルでは抜けが発生しましたが
250×250、500×300では全てのピクセルに指定した輝度値(225)が割り振られていました。
2020/1/16追記「//以下変更点」のようにコードを変えてみましたがピクセル抜けが解消されませんでした。
回答2件
あなたの回答
tips
プレビュー