C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

カラービットマップの描画について

[トピック内 17 記事 (1 - 17 表示)]  << 0 >>

■100272 / inTopicNo.1)  カラービットマップの描画について
  
□投稿者/ まさお (1回)-(2022/07/14(Thu) 14:27:54)

分類:[C#] 

幅が4の倍数ではない201×100(仮)のイメージデータ(カラー)の描画をしたいのですがうまくいきません。
現在、下記のようにやっていますがMarshal.Copyのところでエラーになってしまいます。
(エラー:'保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。')
イメージデータを200×100にして下記引数の201を200にすると期待する描画ができます。

Bitmap bitmap = new Bitmap(201, 100, 204, PixelFormat.Format24bppRgb, IntPtr.Zero))
BitmapData bitmapData = bitmap.LockBits(
new Rectangle(0, 0, 201, 100),
ImageLockMode.WriteOnly,
PixelFormat.Format24bppRgb);
Marshal.Copy(scan0, 0, bitmapData.Scan0, scan0.Length); // ここでエラー

どこが悪いのかご存知のかいらっしゃいませんか?
よろしくお願いします。




引用返信 編集キー/
■100273 / inTopicNo.2)  Re[1]: カラービットマップの描画について
□投稿者/ radian (75回)-(2022/07/14(Thu) 15:27:56)
2022/07/14(Thu) 15:57:03 編集(投稿者)
No100272 (まさお さん) に返信
> 幅が4の倍数ではない201×100(仮)のイメージデータ(カラー)の描画をしたいのですがうまくいきません。
> 現在、下記のようにやっていますがMarshal.Copyのところでエラーになってしまいます。
> (エラー:'保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。')
> イメージデータを200×100にして下記引数の201を200にすると期待する描画ができます。
> 
> Bitmap bitmap = new Bitmap(201, 100, 204, PixelFormat.Format24bppRgb, IntPtr.Zero))
> BitmapData bitmapData = bitmap.LockBits(
>            		new Rectangle(0, 0, 201, 100),
>                 ImageLockMode.WriteOnly,
>                 PixelFormat.Format24bppRgb);
> Marshal.Copy(scan0, 0, bitmapData.Scan0, scan0.Length);     // ここでエラー

とりあえずデバッグして scan0.Lengthと、bitmapDataのStride*Height を確認してみてはいかがでしょう。
下記のコードで、pictureBox1が白色になるのは確認しましたが。

    private void button1_Click(object sender, EventArgs e)
    {
        var scan0 = Enumerable.Repeat<byte>(0xff, (((201 * 3) + 1) * 100) ).ToArray(); //+1はパディング(横一行バイト数を4の倍数にする)
        Bitmap bitmap = new Bitmap(201, 100, 204, PixelFormat.Format24bppRgb, IntPtr.Zero);
        BitmapData bitmapData = bitmap.LockBits(
                    new Rectangle(0, 0, 201, 100),
                 ImageLockMode.WriteOnly,
                 PixelFormat.Format24bppRgb);
        Marshal.Copy(scan0, 0, bitmapData.Scan0, scan0.Length);
        bitmap.UnlockBits(bitmapData);
        pictureBox1.Image = bitmap;
    }

24bitBMPはパディング考慮する必要があり、画像処理する時に32bit単位で1ピクセル纏めて処理とかもしづらいので、32bitBMPの方が扱いやすいと思います。

引用返信 編集キー/
■100274 / inTopicNo.3)  Re[1]: カラービットマップの描画について
□投稿者/ kiku (282回)-(2022/07/14(Thu) 15:37:42)
No100272 (まさお さん) に返信
> どこが悪いのかご存知のかいらっしゃいませんか?
> よろしくお願いします。

下記のことを理解すると、答えがわかると思います。
https://imagingsolution.net/program/csharp/bitmap-data-memory-format/
引用返信 編集キー/
■100284 / inTopicNo.4)  Re[2]: カラービットマップの描画について
□投稿者/ まさお (3回)-(2022/07/15(Fri) 10:28:44)
No100273 (radian さん) に返信
> 2022/07/14(Thu) 15:57:03 編集(投稿者)
>
> ■No100272 (まさお さん) に返信
>>幅が4の倍数ではない201×100(仮)のイメージデータ(カラー)の描画をしたいのですがうまくいきません。
>>現在、下記のようにやっていますがMarshal.Copyのところでエラーになってしまいます。
>>(エラー:'保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。')
>>イメージデータを200×100にして下記引数の201を200にすると期待する描画ができます。
>>
>>Bitmap bitmap = new Bitmap(201, 100, 204, PixelFormat.Format24bppRgb, IntPtr.Zero))
>>BitmapData bitmapData = bitmap.LockBits(
>> new Rectangle(0, 0, 201, 100),
>> ImageLockMode.WriteOnly,
>> PixelFormat.Format24bppRgb);
>>Marshal.Copy(scan0, 0, bitmapData.Scan0, scan0.Length); // ここでエラー
>
> とりあえずデバッグして scan0.Lengthと、bitmapDataのStride*Height を確認してみてはいかがでしょう。
> 下記のコードで、pictureBox1が白色になるのは確認しましたが。
>
> private void button1_Click(object sender, EventArgs e)
> {
> var scan0 = Enumerable.Repeat<byte>(0xff, (((201 * 3) + 1) * 100) ).ToArray();
> Bitmap bitmap = new Bitmap(201, 100, 204, PixelFormat.Format24bppRgb, IntPtr.Zero);
> BitmapData bitmapData = bitmap.LockBits(
> new Rectangle(0, 0, 201, 100),
> ImageLockMode.WriteOnly,
> PixelFormat.Format24bppRgb);
> Marshal.Copy(scan0, 0, bitmapData.Scan0, scan0.Length);
> bitmap.UnlockBits(bitmapData);
> pictureBox1.Image = bitmap;
> }
>
> 24bitBMPはパディング考慮する必要があり、画像処理する時に32bit単位で1ピクセル纏めて処理とかもしづらいので、32bitBMPの方が扱いやすいと思います。

ご回答ありがとうございます。
プログラムを編集して試してみましたがうまくいきません。
下記プログラムでImageWidth が(4の倍数)か(4の倍数-1)の時はうまく動くのですがそれ以外の時にうまく動きません。

kiku 様が教えてくれた下記サイトを見て理解したつもりですが動かない原因が分かりません。

> 下記のことを理解すると、答えがわかると思います。
> https://imagingsolution.net/program/csharp/bitmap-data-memory-format/

何が悪いのでしょうか??
よろしくお願いします。


const int ImageWidth = 100;
const int ImageHeight = 50;

int stride = (ImageWidth * 24 + 31) / 32 * 4;
int dataWidth = (ImageWidth + (stride / 3 - ImageWidth)) * 3;

var scan0 = Enumerable.Repeat<byte>(0x00, (dataWidth) * ImageHeight).ToArray();

// 青のグラデーションになるようなデータ作成
byte c;
for (int y = 0; y < ImageHeight; y++)
{
c = 0;
for (int x = 0; x < ImageWidth * 3; x++)
{
if (x % 3 == 0)
{
int index = y * (dataWidth) + x;
scan0[index] = c;
c+=2;
}
}
}
// --------------------

Bitmap bitmap = new Bitmap(ImageWidth, ImageHeight, PixelFormat.Format24bppRgb);

BitmapData bitmapData = bitmap.LockBits(
new Rectangle(0, 0, ImageWidth, ImageHeight),
ImageLockMode.WriteOnly,
PixelFormat.Format24bppRgb);
Marshal.Copy(scan0, 0, bitmapData.Scan0, scan0.Length);
bitmap.UnlockBits(bitmapData);
pictureBox1.Image = bitmap;




引用返信 編集キー/
■100288 / inTopicNo.5)  Re[2]: カラービットマップの描画について
□投稿者/ radian (77回)-(2022/07/15(Fri) 11:13:57)
2022/07/15(Fri) 11:26:08 編集(投稿者)

もう一度書きますね。

『とりあえずデバッグして scan0.Lengthと、bitmapDataのStride*Height を確認してみてはいかがでしょう。』

単なる計算ミスだと思います。
デバッグの仕方が判らないなら、まずデバッグの仕方を学習してください。
https://docs.microsoft.com/ja-jp/visualstudio/debugger/debugging-absolute-beginners?view=vs-2022&tabs=csharp

あと、うまくいきませんという言葉は使わず、具体的に相手に伝わるように書く努力をしてください。
第三者には何のこっちゃ判らないです。
あなたは、病院で医者に病気の症状伝えるときに、なんか調子悪いですとしか言わないんですか?
引用返信 編集キー/
■100291 / inTopicNo.6)  Re[3]: カラービットマップの描画について
□投稿者/ まさお (5回)-(2022/07/15(Fri) 11:28:22)
No100288 (radian さん) に返信
> もう一度書きますね。
>
> 『とりあえずデバッグして scan0.Lengthと、bitmapDataのStride*Height を確認してみてはいかがでしょう。』
>
> 単なる計算ミスだと思います。
> デバッグの仕方が判らないなら、まずデバッグの仕方を学習してください。
> https://docs.microsoft.com/ja-jp/visualstudio/debugger/debugging-absolute-beginners?view=vs-2022&tabs=csharp

すいません。
色々試していて間違ったコードのまま貼り付けてしまいました。
(誤)var scan0 = Enumerable.Repeat<byte>(0x00, (dataWidth) * ImageHeight).ToArray();
の部分は
(正)var scan0 = Enumerable.Repeat<byte>(0x00, stride * ImageHeight).ToArray();

となっておりscan0.Lengthと、bitmapDataのStride*Heightが同じ値になっているのは確認済みです。
ImageWidth が(4の倍数)か(4の倍数-1)のときは期待するように青のグラデーションが表示されるのですが
それ以外の時におかしな表示になってしまうのです…
引用返信 編集キー/
■100292 / inTopicNo.7)  Re[4]: カラービットマップの描画について
□投稿者/ radian (78回)-(2022/07/15(Fri) 11:30:07)
2022/07/15(Fri) 11:33:06 編集(投稿者)

No100291 (まさお さん) に返信
> (正)var scan0 = Enumerable.Repeat<byte>(0x00, stride * ImageHeight).ToArray();

ちなみに、初期値セットしたいからEnumerable.Repeat使っただけなので、
初期値0でいいなら単純に new byte[確保サイズ] でいいです。
引用返信 編集キー/
■100295 / inTopicNo.8)  Re[4]: カラービットマップの描画について
□投稿者/ kiku (283回)-(2022/07/15(Fri) 11:38:14)
No100291 (まさお さん) に返信
> ■No100288 (radian さん) に返信
> となっておりscan0.Lengthと、bitmapDataのStride*Heightが同じ値になっているのは確認済みです。
> ImageWidth が(4の倍数)か(4の倍数-1)のときは期待するように青のグラデーションが表示されるのですが
> それ以外の時におかしな表示になってしまうのです…

現在の最新のソースはどのようになっているのでしょうか?
一番最初に提示されたソースは、scan0が定義されていないので
なんともコメントの付けようがなかったです。
最小のソースで、動作する最新のソースの開示が必要かと思います。
そうすると、いろいろな人からコメントが付く可能性が高まると思います。

引用返信 編集キー/
■100297 / inTopicNo.9)  Re[3]: カラービットマップの描画について
□投稿者/ KOZ (293回)-(2022/07/15(Fri) 11:42:15)
No100284 (まさお さん) に返信
> プログラムを編集して試してみましたがうまくいきません。
> 下記プログラムでImageWidth が(4の倍数)か(4の倍数-1)の時はうまく動くのですがそれ以外の時にうまく動きません。

「うまく動きません」の内容が変わってます。
2箇所修正したら動きました。dataWidth って不要なのでは?

protected override void OnPaint(PaintEventArgs e) {
    base.OnPaint(e);

    int left = 10;

    for (int i = 0; i < 4; i++) {
        int ImageWidth = 100 + i;
        const int ImageHeight = 50;

        int stride = (ImageWidth * 24 + 31) / 32 * 4;
        int dataWidth = (ImageWidth + (stride / 3 - ImageWidth)) * 3;

        //var scan0 = Enumerable.Repeat<byte>(0x00, (dataWidth) * ImageHeight).ToArray(); ★ここ
        var scan0 = Enumerable.Repeat<byte>(0x00, stride * ImageHeight).ToArray();

        // 青のグラデーションになるようなデータ作成
        byte c;
        for (int y = 0; y < ImageHeight; y++) {
            c = 0;
            for (int x = 0; x < ImageWidth * 3; x++) {
                if (x % 3 == 0) {
                    //int index = y * (dataWidth) + x;  ★ここ
                    int index = y * (stride) + x;
                    scan0[index] = c;
                    c += 2;
                }
            }
        }

        using (Bitmap bitmap = new Bitmap(ImageWidth, ImageHeight, PixelFormat.Format24bppRgb)) {
            BitmapData bitmapData = bitmap.LockBits(
                new Rectangle(0, 0, ImageWidth, ImageHeight),
                ImageLockMode.WriteOnly,
                PixelFormat.Format24bppRgb);
            Marshal.Copy(scan0, 0, bitmapData.Scan0, scan0.Length);
            bitmap.UnlockBits(bitmapData);
            e.Graphics.DrawImage(bitmap, new Point(left, 10));
        }
        left += ImageWidth + 10;
    }
}


引用返信 編集キー/
■100300 / inTopicNo.10)  Re[4]: カラービットマップの描画について
□投稿者/ radian (79回)-(2022/07/15(Fri) 11:46:27)
代理デバッグは本人の為にならないからやめた方がいいっすよ。
引用返信 編集キー/
■100302 / inTopicNo.11)  Re[5]: カラービットマップの描画について
□投稿者/ KOZ (294回)-(2022/07/15(Fri) 12:26:02)
No100300 (radian さん) に返信
> 代理デバッグは本人の為にならないからやめた方がいいっすよ。

場合によりますね。
デバッグすればすぐわかるようなときならしませんが、これはデバッグしたところでわかりにくい問題かと。
引用返信 編集キー/
■100303 / inTopicNo.12)  Re[6]: カラービットマップの描画について
□投稿者/ radian (80回)-(2022/07/15(Fri) 12:34:49)
2022/07/15(Fri) 12:37:52 編集(投稿者)

No100302 (KOZ さん) に返信
> ■No100300 (radian さん) に返信
>>代理デバッグは本人の為にならないからやめた方がいいっすよ。
>
> 場合によりますね。
> デバッグすればすぐわかるようなときならしませんが、これはデバッグしたところでわかりにくい問題かと。

いやdataWidthの値見たらすぐ判るでしょ…
気付けるように色々ヒントも書いてる。
もうほぼ自力で正解辿り着けそうなとこまできてるんだから
そこは答え書くべきじゃない。
引用返信 編集キー/
■100304 / inTopicNo.13)  Re[7]: カラービットマップの描画について
□投稿者/ KOZ (295回)-(2022/07/15(Fri) 12:53:29)
No100303 (radian さん) に返信
> いやdataWidthの値見たらすぐ判るでしょ…
> 気付けるように色々ヒントも書いてる。
> もうほぼ自力で正解辿り着けそうなとこまできてるんだから
> そこは答え書くべきじゃない。

「それってあなたの感想でしょ」ってやつですね。
間違った内容を書いてるならともかく、レスのつけ方まで文句をいわれるすじあいはありません。
不毛なのでやめときましょう。
引用返信 編集キー/
■100305 / inTopicNo.14)  Re[8]: カラービットマップの描画について
□投稿者/ radian (81回)-(2022/07/15(Fri) 13:04:06)
2022/07/15(Fri) 13:24:58 編集(投稿者)

No100304 (KOZ さん) に返信
> ■No100303 (radian さん) に返信
>>いやdataWidthの値見たらすぐ判るでしょ…
>>気付けるように色々ヒントも書いてる。
>>もうほぼ自力で正解辿り着けそうなとこまできてるんだから
>>そこは答え書くべきじゃない。
>
> 「それってあなたの感想でしょ」ってやつですね。
> 間違った内容を書いてるならともかく、レスのつけ方まで文句をいわれるすじあいはありません。
> 不毛なのでやめときましょう。

本人がデバッグ方法を身に付けるってのが重要な訳で、
あなたは答え貼り付けて自己満足するだけでいいと思うけど、
それによって、デバッグ方法を身に付ける機会を奪ってるって事だけは理解してください。
単なる計算ミスで、再度同じような質問をしないように気付きを与えたいのです。

それでも、うるせぇな質問相手の事は知ったこっちゃないし
自分は答えそのまま貼りつけたいんだよ!というなら、
もはや特に何も言う事はありませんが。
引用返信 編集キー/
■100306 / inTopicNo.15)  Re[9]: カラービットマップの描画について
□投稿者/ kiku (284回)-(2022/07/15(Fri) 13:13:47)
radianさん
KOZさん

私見ですが、どちらも正しいと思います。
どちらを要望されているかは質問者さんしかわかりません。
質問者さんの応答を待ちましょう。

引用返信 編集キー/
■100307 / inTopicNo.16)  Re[10]: カラービットマップの描画について
□投稿者/ radian (82回)-(2022/07/15(Fri) 13:17:01)
No100306 (kiku さん) に返信
> radianさん
> KOZさん
>
> 私見ですが、どちらも正しいと思います。
> どちらを要望されているかは質問者さんしかわかりません。
> 質問者さんの応答を待ちましょう。

そうですね、ちょっと熱くなりすぎました。
失礼しました。
引用返信 編集キー/
■100320 / inTopicNo.17)  Re[5]: カラービットマップの描画について
□投稿者/ まさお (7回)-(2022/07/15(Fri) 18:34:56)
解決しました!
やはりご指摘の通りケアレスミスでした。
そもそもの考え方が間違っていると思い込み計算等の確認がおろそかになってしまったようです。

ご回答いただいたみなさんありがとうございました。
解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ