バグ:アルファチャンネルありの32bitBMPが、カード種別によってはアルファチャンネルが無視される

Issue #1019 resolved
ルンバ created an issue

添付画像のようなアルファチャンネルありの32bitBMPカードが、アイテム、召喚獣、技能、情報カードのみアルファチャンネル部が純白扱いでマスク色として認識されてしまうようで、ハイライト部とかの純白描画部もマスクされてしまいます。
1.50やNEXTでは無い症状で、xエディター上でも正常に描画されますがPyエンジン上では情報カードのみにこの現象が見られます。

Comments (17)

  1. k4nagatsuki repo owner

    ご報告ありがとうございます。

    ちょっと手元に環境を作るのが大変なので、当該画像を用意していただけると助かります。

    情報カード以外でおかしくならないというのがちょっとよく分からないのですが、メニューカードでも異常は出ないのでしょうか?

  2. ルンバ reporter

    メニューカードやセリフコンテンツでは異常は出ないです。が、すみません、手札カードでも異常が出ます。

    ここの画像添付はBMPが読み込まれない仕様ですか? ASKのBMP素材その他でも拒否されます。

  3. ルンバ reporter

    □の中がマスク扱いになります。

    キャストや背景セルでは正常です。

  4. k4nagatsuki repo owner

    確認しました。

    CW 1.50で導入された32-bitビットマップは(おそらく)独自仕様で、RGBの3バイトの直後にある4バイト目がすべて0ないし255でない時に限ってα値として扱われるような形になっています。pygameでイメージを読み込んだ時にはその4バイト目が残ったバッファにアクセスできるので、CWPyのpygame側では特別にそのデータからα値を取り出して透明色として設定し直す処理を行っています。

    しかしwxPython側でイメージファイルを読み込んだ後でCW 1.50が独自にα値とみなしている4バイト目にアクセスする方法は見つけていません。今回の問題はそれに起因するものです。

    そうなるとビットマップのデータ部分を読み込む処理を独自に作って4バイト目を取り出すしかないのですが、規格が多すぎてきちんと対応するのは恐ろしく面倒です。正直なところ、実際にこれによって問題の発生するシナリオが存在しない限りは対応したくありません。そうしたシナリオは存在するのでしょうか?

  5. ルンバ reporter

    これによって問題の発生するシナリオはみた事はないのですが、潜在的には問題は発生していると思います。

    まず透過PNG素材はけっこうふつうにあります。そしてPyだとWSMシナでのPNG使用に制限があるので透過PNGを透過BMPに変換せざるを得ないです。
    そうするとハイライトや単に固有色として純白を使っているカードなど珍しくないので、このバグが発生します。
    これが問題になる透過PNG素材を配布している著名な素材作家は複数あげられます。

    一見、バグが発生するシナリオが存在しないのは、Pyエンジンでテストプレイをすると原因不明のこの症状に突き当たる事でその素材の使用が回避されるか、透過を諦めるなどの問題が起きているからだと思います。

    カードの種類に応じて透過PNGのまま使用するのと透過BMPに変換したものを使い分ければ一応の対策にはなりますので、この症状が出るケースはxエディター上で警告を出すという方針でも良いでしょう。

    警告があれば変換処理を行えるようなシナリオ作者なら純白部を色調補正する等の回避を行うかもしれませんし、素材作者にもこの問題が認知されれば透過PNG内の純白描画色は最初から明度を-1するとかしてもらえる可能性もあります。

  6. k4nagatsuki repo owner

    一つ認識違いがあると思うのですが、この問題は白でなくても発生するはずです。今回のイメージで白(255,255,255)が透過されているのは、左上が白だからです。

  7. ルンバ reporter

    たしかに透過PNGを作る場合に背景色を純白以外にして背景をアルファチャンネル化すれば左上は純白以外にもなり描画領域でも純白は使えます。
    描画領域内でその純白からのグラデーション部に使われない色相で純白スレスレの色を背景色にあてる事でも描画領域内での純白規制は避けられますね。そういう回避の選択も含めて少なくとも警告は欲しいところではないでしょうか。

  8. k4nagatsuki repo owner

    32-bit Bitmapにはおそらく規格が存在せず(少なくとも私は見た事がない)、アプリケーションによってまちまちに実装されています。CW 1.50の実装は全ピクセルを走査しなければα値が存在するか分からない性質のものであり、その型の実装になっているか調べるには大量の処理が必要です。

    その上、規格がない以上、CW 1.50的に壊れているものと他のアプリケーションから見て壊れているものとの境界は曖昧です。以上により、警告を出すとしたら32-bit Bitmap全部に出すのが妥当という事になります。

    また、上記のような理由で32-bit Bitmapに警告を出すのであれば、壊れたイメージデータ全てに警告を出さなければ一貫性がありません。ちゃんとやるなら以下のどちらかを選ぶ必要があります:

    1. 全て警告する
    2. 黙って対応する

    しかしながらWirthBuilderにはイメージデータを変換で破壊してしまうバグがあり(fiximage160を参照してください)、CWの世界には壊れたデータがあまりにも広く存在しすぎています(WBの変換機能は「使うべきでない」を通り越して「使ってはいけません」が、実際にはそのようなメッセージを発しても必要な層に届かないでしょう)。

    また、イメージデータにはWBの壊し方以外にも色々な壊れ方があります。1番目の選択肢は修羅の道で、そちらは採れません。そうなると2番目の選択肢を選ぶ事になりますが、これは上記した通り手間がかかるので私のモチベーションが上がりません。


    つまるところ今回の問題は私のモチベーションに帰着します。対応する方法は上記の通り分かっていますが、ぶっちゃけてしまうと、私はこのWBの変換機能にまつわる問題に何十時間も吸い取られてうんざりしており、ましてレアケースで既存のシナリオに問題も出ていないものとなると、よほど気分のいい時でなければ作業できません。

    もちろんCWPyはオープンソースなので、それなら実装してやるか、というような方がいらっしゃったら喜んでレビューさせていただきます。

    ヘッダの種類が大量にある事と、データが上下逆になっているケースに注意すれば妥当な実装にはなると思います。bfOffBitsはWBの生成した画像である場合あてにできません(大抵壊れています)。ヘッダを全部読む必要があります。RLE圧縮は、32-bitではたぶんされていません。α値の検出についてはすでに関数があります。

  9. ルンバ reporter

    関連して気になった点なのですが、

    ① XEditorで作成したWSMシナでBMP絵でカードを作成
    ② それをWirthBuilderで開き、カードの画像を別のPNGに置き換え上書きし保存
    ③ 再びXEditorで開くとWirthBuilderで保存したPNG画像が消え、①時点でのXEditorで設定したBMP画像に戻っている
    ④ ③を保存せず②のデータのままゲームエンジン上で開くと1.50もPyも②で保存した画像で再現される

    ③の挙動はWBの画像変換から元画像を保護するための意図的な挙動なのでしょうか?

  10. ルンバ reporter

    本題に戻りますと警告も含めて技術的に難しいという事は了解しましたが、最後に確認させていただきます。

    シナリオ内では問題症状がなかったキャストカードも宿へ連れ込む事によって問題症状が発生してしまう事を確認しました。
    これはシナリオ外への持ち出し可能なカード絵には仰る様な技術的問題が伴うという事かと思います。

    そこで、シナリオ内で完結する情報カードだけでも、仰る技術的問題を回避して、メニューカード等と同じような画像の扱いで問題症状が発生しない様にする事は可能でしょうか?(あるいはキャストカードがシナリオ内では正常に表示されるように)

    手持ちの素材を参照した限りでは透過PNGの使用例は顔絵が過半数のようです。(例えばアレンジパック作者の方のように最近はそうした透過PNG中心で素材を提供しているケースもあります)そして情報カードにキャストカードを用いるケースは割とよくある事でもありますのでそこだけでも互換性を保てるならその方が良いでしょう。

  11. k4nagatsuki repo owner

    まず実際に起きている現象について説明します。

    1. 宿へ連れ込む事で表示方法が変わる事はありません。
    2. CWPyはwxWidgets(wxPython)とpygameの2つのライブラリで構築されており、今回問題の起きているのはwx側です。
    3. wxはダイアログ等メインのゲーム画面以外の表示を担当しています。
    4. 従って、大雑把にダイアログ上で表示される時に問題が起きると考えるとよいでしょう。

    画像が変化する件ですが、cwxeditorのカードイメージの参照情報を保存する設定がオンになっていませんか? cwxeditorで開いた時に参照情報があるとそちらの方が優先されます。

    最後に、これは技術的に難しいのではなく、単に面倒というのが実態です(やってみたら大抵別の問題が出て、それも面倒なのですが)。対応方法は上の方に書いた通りです。

  12. ルンバ reporter

    関連して気になった点の②③でWBとXEditorで画像が変わる件は、たしかに、参照情報を保存する設定がオンになっていました。

    また課題本題の問題発生についても、ダイアログ上か否かという説明で理解できました。
    シナリオ内のメニューやキャストはダイアログでないので正常に表示される。その他カードはダイアログ上で扱われるので症状発生。
    連れ込みの際の「不足データの補填」ウインドウとアルバム上の表示(ダイアログ上)では問題症状が発生する。
    編入しパーティメンバーに加えると(ダイアログ扱いから外れるので)正常表示。
    当然パーティから外し、アルバム上に戻すと(ダイアログ扱いになるので)問題症状は発生。

    という事だったわけで、たしかに宿で連れ込んでも表示方法は原理的には変わっていないです。
    (連れ込みしたキャストはアルバム上では症状が発生しているわけですが)

    そして私の要望はキャストやメニューの描画方式で情報カードだけでも描画できないかという事だったわけですが
    それはwxWidgets(wxPython)とpygameの2つのライブラリで別に行っているので無理がある。
    と理解できましたのでこれ以上の要望はありません。

    一応タイトル等をわかりやすく整理し課題は残しておきます。

  13. k4nagatsuki repo owner

    pull request #212

    途中いろいろ迷走して時間をとられましたが、結果的には思ったよりは少ないコード量で対応できました。該当イメージの32-bitビットマップのピクセルデータの量がヘッダのファイルサイズ情報と不一致になっていたせいで結果がおかしくなっていたようです。

    大抵のビットマップファイルはもともと大丈夫だと思います(でもWBがそういうファイルを作っている可能性がある)。

  14. ルンバ reporter

    透過PNG素材をフォトショップで32bit透過BMPに変換した画像もダイアログ上で正常に表示されるようになる事確認しました。対応ありがとうございました。

  15. Log in to comment