TBitMapのPixelFormat

解決


earthed  2006-08-03 03:02:25  No: 22806

TBitmap.PixelFormatの値がpf8bitの場合(256色)、白色は$FFで良いでしょうか?
そして、白色より一段階黒に近い色は1引いて$FEで良いでしょうか?
後、8ビットの色をTColor型に変換する計算方法を教えてください。


sadoyama さどやま  URL  2006-08-03 04:17:29  No: 22807

pf8bit だけではなく、 4bit, 1bit も白色はやはり $FFFFFF の3バイト値です。

pf8bit 以下は、各ピクセルの色をパレットで色指定します。
パレットは、3バイトのカラー値の配列です。

pf8Bit なら、配列の添え字は 0..255 です。
パレット配列[0] に $FFFFFF が格納されていた場合に、
あるピクセルの色情報が [0] となっていると
TBitmap はそのピクセルの色値をパレット配列[0]から取り出して白色で描画します。
このピクセルの色情報を8ビットの値(0..255)で格納するBitmapが pf8bit です。

pf24bit は、1ピクセルの色情報を24ビットで表します。
1ピクセルに24ビットを使うのであれば、パレットを使う必要は無く、直接カラー値そのもので表せばよいわけです。

要するに、8ビット以下はデータ圧縮の一種と言えます。
16, 32ビットは 少し特殊です。

検索で  Bitmap, フォーマットを捜すと、パレットがある場合とない場合が理解できるでしょう。


earthed  2006-08-03 05:08:30  No: 22808

ありがとうございます。
24bitの場合は直接ピクセルの色を表現して、8bit以下の場合は、
色のテーブル(パレット)のインデックスを保持するという事ですね。
どのbit数でもそのビットで色を表現するものだと思っていました。
パレット等について調べてから、再度質問します。


earthed  2006-08-03 05:55:27  No: 22809

システムパレットと、20の予約色があるというところまで分かりました。
予約色(Delphiで定数宣言されている色)のみ使用して描画する場合は特にパ
レットは意識しなくて良いのでしょうか?

プログラム内では特定のピクセルが白色かどうか判断したいのですが、
最初に定義した条件のTBitmap.PixelFormatの値がpf8bitの場合、
TImageコンポーネント内のBitmapオブジェクトのScanlineで取得したピクセル
列の該当の1バイトの値が$FF(システムパレットでの白のインデックス)か
判断するというやり方で良いでしょうか?

>白色より一段階黒に近い色は1引いて$FEで良いでしょうか?
これは白く見えるけど透過されない色を表現したかったので、clCreamで
実現させました。


sadoyama さどやま  URL  2006-08-03 19:36:46  No: 22810

とりあえず
> 白色より一段階黒に近い色は1引いて$FEで良いでしょうか?
についてのみ

$FFFFFE, $FFFEFF, $FEFFFF のどれかということになります。
どれを選ぶかは各人の作風です。

肉眼ではどれも $FFFFFF に見えるでしょうが、
透過色が $FFFFFF にしてあれば、コンピュタは見分けることができます。


jok  2006-08-03 20:06:15  No: 22811

なんだか、一般論とパレットの内容とがごっちゃになってますね。

PixelFormat が pf8bit の場合は、

ビットマップのおのおののピクセルのデータがパレットのインデックスである。

ということが重要です。つぎに、デフォルトのパレットエントリはどうなってるか?
つまり、なにも操作しない場合にVCLでつくられるビットマップのパレットエントリ
がどうなってるか、を知ることが重要です。これは

http://junki.main.jp/delphigr/008PaletteEntries.htm

を見れば分かります。
つぎに、パレットを持っている画像に、任意の色で描画したらどうなるか? ですが
VCL では、「もっとも近い」パレットエントリに強制的に変換させられます。

> プログラム内では特定のピクセルが白色かどうか判断したいのですが、

これに厳密に回答すると、
1)パレットの内容を調べて、エントリのなかに R=255 G=255 B=255 のエントリの
インデックスを求める。
2)「特定のピクセル」の色データが上のエントリと一致しているかどうか調べる。

> 白色より一段階黒に近い色は1引いて$FEで良いでしょうか?

これが成り立つのは、グレイスケールで、かつパレットが正規化されている場合だけです。
一般のパレットエントリではまったく成り立ちません。パレットエントリのなかに
白が必ずあるとは限らず、あったとしても「白色より一段階黒に近い色」は、
どのパレットエントリになるか、には一般的な回答はありません。


jok  2006-08-03 20:13:29  No: 22812

> プログラム内では特定のピクセルが白色かどうか判断したいのですが、

厳密には上に書いたとおりですが、簡単には、Pixels[] で色を取得して
の RGB 成分を見ると分かります。


earthed  2006-08-03 22:39:58  No: 22813

>ビットマップのおのおののピクセルのデータがパレットのインデックスであ
>る。ということが重要です。つぎに、デフォルトのパレットエントリはどう
>なってるか?つまり、なにも操作しない場合にVCLでつくられるビットマップ
>のパレットエントリがどうなってるか、を知ることが重要です。

パレットをプログラムから操作せず予約色のみで描画している場合は、システ
ムパレットがそのまま参照できると思っていても良いのでしょうか?

>厳密には上に書いたとおりですが、簡単には、Pixels[] で色を取得して
>の RGB 成分を見ると分かります。
この方法も試してみたのですが、時間が掛かりすぎてボツになりました。


sadoyama さどやま  URL  2006-08-06 01:41:21  No: 22814

>> 厳密には上に書いたとおりですが、簡単には、Pixels[] で色を取得して
>> の RGB 成分を見ると分かります。
> この方法も試してみたのですが、時間が掛かりすぎてボツになりました。

  例えばマウスでクリックしたピクセルの色値を得るのなら Pixels[] が便利ですが、全ピクセルの色値をチェックするとなると ScanLine を使うしかありませんね。

  ところで、実現したいことですが、次のような理解でよいのでしょうか。

1.各ピクセルの色値を得る。
    (ScanLine で得られる各ピクセルの値はパレットのインデックス値)
2.その色値が clWhite であれば、白に見えるが clWhite ではない色に変えたい。

  ただこの場合、なぜ clWhite を透過色に指定するのか、私には意味が解りません。透過そのものを使わなければ最初から実現しているわけですから。


かみづ  2006-08-06 04:55:56  No: 22815

パレットを処理するのが面倒ならpf24bitに変更してから処理すればよいのでは?


earthedn  2006-08-06 06:22:53  No: 22816

>さどやま様
実現したい処理は、少し前に質問スレッドを立てたのですが、画像の重ね合わせ
処理を行いたいのです。
https://www.petitmonte.com/bbs/answers?question_id=4152
上記であげた処理の3番目のロジックを作りこんでいます。
こう少し簡単に出来る方法があればよいのですが、今のところ思いついた方法
はこれだけしかありません。
処理の手順として
1.背景用画像をTPictureオブジェクトに読み込んでおく。
  ビットマップではあるが、その色数の画像が指定されるかは分からない。
TBitmap.PixelFormatの値がpf8bit


earthed  2006-08-06 06:34:26  No: 22817

途中で送信してしまいました。

実現したい処理は、少し前に質問スレッドを立てたのですが、画像の重ね合わ
せ処理を行いたいのです。
https://www.petitmonte.com/bbs/answers?question_id=4152
上記であげた処理の3番目のロジックを作りこんでいます。
こう少し簡単に出来る方法があればよいのですが、今のところ思いついた方法
はこれだけしかありません。
処理の手順として
1.背景用画像をTPictureオブジェクトに読み込んでおく。
  ビットマップではあるが、その色数の画像が指定されるかは分からない。
  PictureオブジェクトのBitmapプロパティをPixelFormatの値をpf8bitにす
る。

2.フォームに貼り付けたTImageコンポーネントに対するマウスの操作により
画像を描画する。
表示されているImageコンポーネントには直接行わず、隠してあるImage
コンポーネントに対して描画する。
(描画用のImageコンポーネントもpf8bitにしておく)
そしてフォーム上のImageコンポーネントに予め読み込んだ背景用画像をコピー
し、その後描画したImageコンポーネントのピクセルを操作し、白色以外なら
表示用のImageの該当するピクセルに色を転記する。

Imageコンポーネントのマウスムーブとマウスダウンのイベントで上記の
2の処理を行っています。

>かみづ様
画像ファイルが大量に作成される可能性があるので出来るだけ容量を抑える為
にと思い8ビットの画像にしてあります。
ただ、8ビットでも枚数が増えると容量がかなり増えるので圧縮して保存する
方向で考えているのですが、圧縮すると8ビットでも24ビットでもサイズが
変わらないようなので、パレットの心配をしなくて良い24ビットでも
よいような気がしてきました。


earthed  2006-08-06 07:10:38  No: 22818

ちょっと質問があいまいになってしまっている気がしますので整理します。
8ビットのビットマップで描画を行うとして、プログラムでパレットの変更は
行わず、予約色(TColor型で定義されている色)のみを使う場合は、システム
パレットのインデックスをそのまま使えると想定しておいて問題ないのでしょうか?
(プログラムで判定するのは白色だけなので、該当の1バイトがFFがどうかの
条件で問題ないか?それとも都度パレットを調べて白色に該当する値を調べる
必要があるのか?)


えーと  2006-08-06 07:28:53  No: 22819

どうも、なにが質問の意味なのかわかりません。
パレットの内容は、自分で操作しない限り、自動で変更されたりはしません。
だから、FF番目が白と確信できるなら、なぜ質問するのか理解できません。


なので  2006-08-06 08:58:44  No: 22820

えーとさんの仰るとおりです。
裏を返せば他のアプリで作成した8ビットのビットマップのFF番目が白とは保証されません。


sadoyama さどやま  URL  2006-08-07 17:40:34  No: 22821

パレットについては詳しくないので、間違っていたら誰かフォローしてください。

> プログラムで判定するのは白色だけなので、
> 該当の1バイトがFFがどうかの条件で問題ないか?
> それともその都度パレットを調べて白色に該当する値を調べる必要があるのか?

  既に指摘があったように $00FFFFFF のインデックスが $FF とは限りません。
  また、通常(Delphi VCL などのように Windows API を使用して作成されたもの)はともかく、$00FFFFFF に限らず、予約色が必ず含まれているとも限りません。
  従って、パレット内に $00FFFFFF があるかないかを事前に調べ、
  あればそのインデックスの値を得ることが必用だと理解しています。

> 予約色(TColor型で定義されている色)のみを使う場合は、
> システムパレットのインデックスをそのまま使えると想定しておいて
> 問題ないのでしょうか?

  Windows コントロールパネルの「画面プロパティ|設定|画面の色」で True Color(24 or 32 ビット)が選択可能になっていて、かつ選択されていればパレットの構成がどのようになっていてもすべて使えるはずです。
  そうでない場合、つまり、ビデオカード・モニタが High Color や 256色までしか対応していない場合にはこのような心配が必要になります。
  今となっては、そういう心配はまず無いか、あっても無視してよい時代になっているのではないでしょうか。

  理論的な問題としての(古いデバイスをまだ使っている人には現実的だが)
「システムパレットのインデックスをそのまま使える」かどうかという点は、私の守備範囲の外なので、確信を持って「そうだ」とは言えません。


sadoyama さどやま  URL  2006-08-07 18:12:16  No: 22822

私の考えが正しいかどうかは別にして、
  私の真意を正確に表現できていませんでした。

> Windows コントロールパネルの「画面プロパティ|設定|画面の色」で 
> True Color(24 or 32 ビット)が選択可能になっていて、
> かつ選択されていれば
の後の

> パレットの構成がどのようになっていてもすべて使えるはずです。

  パレットの色配置構成がどのようになっていても、
  パレットで指定された色が使用されるはずです。
  したがって、パレット内に配置されていない予約色があれば、当然使えない。


レイヤ  2006-08-07 21:26:10  No: 22823

透過色を白にしたいというのはいいとして
画像の重ね合わせについて方向が違うような気がします
前スレ
https://www.petitmonte.com/bbs/answers?question_id=4152
で deldelさんが書かれているように一般的にはマスク画像を用意して処理を行います


レイヤ  2006-08-07 21:27:51  No: 22824

上記はearthednさんへの意見です


レイヤ2  2006-08-07 21:37:03  No: 22825

MouseMoveについてくるように画像を動かしたいならリージョンを利用するとスムースに処理できます


earthed  2006-08-08 08:46:32  No: 22826

>さどやま様
現状は動いているのですが、パレットを調べて白色のインデックスを取得する
ロジックは組み込むようにします。

>レイヤ様
マスクイメージというのはカラーで書き込んだ画像をモノクロにしたもの、と
いう感じで使えるのでしょうか?
取りあえず第一フェーズの納品が近いので、その後レイヤーを試してみたいと
思います。

>レイヤ2様
MouseMoveのイベントを処理しているのは、マウスの軌跡に沿って絵を描いたり
しているので、画像をマウスに沿って移動させたりしているのではありませ
ん。
ただ、リージョンと言う処理は知らないので、調べて今後の開発に活かしたい
と思います。

皆様、多数のレスを頂きありがとうございました。
画像の処理が初めてなもので、こちらの状況を明確に出来なかったりとお手数
をお掛けしました。
次回もよろしくお願いします。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加