DxLibEx icon indicating copy to clipboard operation
DxLibEx copied to clipboard

色空間をあつかうクラスの作成

Open yumetodo opened this issue 9 years ago • 20 comments

#1 より

色空間同士の変換

1

赤線:劣化しない(高速化のためにbit演算にした時の計算誤差は考慮しない) 青線:劣化する

full:0-255 com:16-235

BT601:ITU-R BT.601のこと BT709:ITU-R BT.709のこと

COLORREF:Win32APIの色を扱う型 *HSVとHSBについて:本来どちらも同じだが、0-100%で表すか0-255で表すかで分けた。

暗黙変換しないもの同士については、color_castをつくる(少なくともADLで見つかるようにし、名前空間を書かなくて良いようにする)。

YUV系の実装のイメージ(仮)

namespace dxle::color {
    enum color_range : uint8_t {
        full,
        compress
    };
    enum covert_algorithm : uint8_t {
        BT601,
        BT709
    };
    template<color_range range, covert_algorithm  alg> class yc48;
}

べつにtemplate使わなくてもいいですが、この方が楽だと思いまして

参考サイト

  • http://ofo.jp/osakana/cgtips/hsb.phtml
  • http://www.marumo.ne.jp/bt601/
  • http://www.peko-step.com/tool/hsvrgb.html
  • http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
  • https://e182bb01e8864f37f9ce365b879822eb6da3f1f1.googledrive.com/host/0B-PAN4aatmy1ZGctNFU0YlFJc2c/doc/aviutlyc.html
  • https://onedrive.live.com/view.aspx?cid=6BDD4375AC8933C6&resid=6BDD4375AC8933C6!755

yumetodo avatar Dec 15 '15 08:12 yumetodo

論点

  • 上の図は正しいのか?
  • 劣化するものはキャスト必須として、劣化しないけどキャストするべきなのはどれだろうか
  • ~~キャストは、static_castにするか独自にcolor_castを作るべきか。(後者のほうがいい気がする)~~
  • どれを実装するか(全部はいらないんじゃないか説)
  • これを引数に取る関数にスレッドセーフ保障は必要か

yumetodo avatar Dec 15 '15 08:12 yumetodo

とりあえず。

キャストは、static_castにするか独自にcolor_castを作るべきか。

color_castを作りましょう。

これを引数に取る関数にスレッドセーフ保障は必要か

DrawLine系のスレッドセーフの話をしたのはScreenの方のスレッドセーフに絡むからです。

Nagarei avatar Dec 15 '15 10:12 Nagarei

DrawLine系のスレッドセーフの話をしたのはScreenの方のスレッドセーフに絡むからです。

手間が2倍ですが、必要かなと。

yumetodo avatar Dec 15 '15 11:12 yumetodo

相互変換の実装を考えてみました。 全てのクラスが

  • RGBに暗黙に変換できる
  • RGBから明示的にコンストラクトできる

を満たすようにすれば、color_castを多様性を保ちつつ

template<typename to, typename from>
to color_cast(from&& bace)
{
    return static_cast<to>(std::forward<from>(bace));
}

のように単純に実装できます。 これで問題ないでしょうか?

Nagarei avatar Dec 16 '15 02:12 Nagarei

YUY2もRGBと直接変換可能にするんでしょうか?

あとDxLib型式やCOLORREFへの変換はどうしましょう。

enumつくってcolor_castのtemplate実引数に指定することをイメージしているんですが。

yumetodo avatar Dec 16 '15 02:12 yumetodo

いろいろ不安だったのでTwitterで聞いてみました。

‏MaverickTse https://twitter.com/MaverickTse/status/676948740662501376 @yumetodo YC48はchannelごと4096段階あるので、RGB24に変換する場合rounding/downsamplingが必要になる 11:15 - 2015年12月16日

yumetodo https://twitter.com/yumetodo/status/676949133815623681 @MaverickTse つまりYC48->RGB(24bit)は劣化の可能性あり、と? 11:17 - 2015年12月16日

MaverickTse https://twitter.com/MaverickTse/status/676949720888143872 @yumetodo 情報が減っているので理論上劣化する。でもソースがHDRではない限り大体目に見えないほうど 11:19 - 2015年12月16日

yumetodo https://twitter.com/yumetodo/status/676950107468791808 @MaverickTse YUY2(16-235)->YC48(com)->YC48(full)->RGB(24bit)とかやるとどうなるんだろうか 11:20 - 2015年12月16日

MaverickTse https://twitter.com/MaverickTse/status/676950808177561600 @yumetodo ソースが0xFF以内ので大丈夫。com->fullのrounding error除くなら 11:23 - 2015年12月16日

とのことだったので、YC48を介さずにRGBへの変換を作るほうがいいのかもしれない。YUY2->RGB

yumetodo avatar Dec 16 '15 02:12 yumetodo

There is no reason to use an intermediate format. Colorspace/format conversion is expensive and should be done in 1-step if possible.

If for some reason you want a common format for data exchange, consider float32.

This is because all CPU and GPU nowadays has native support for float32 (and int32) calculation, while support for short is minimal

YC48 is an odd thing as it is 3x short:

struct PIXEL_YC{
short y; //-2048~+2048
short cb; //0~4096
short cr; //0~4096
}

please refer to filter.h of AviUtl SDK for details. Actually 3x short is not good for memory alignment... I'd not recommend it unless you have some special needs.

MaverickTse avatar Dec 16 '15 07:12 MaverickTse

可能な限り一度の処理で変換するとなると、やっぱり直接変換のコンストラクタかoperatorを作るしかないですね。そうするとコンストラクタとoperatorのどっちを作るべきなんでしょう?

Nagarei avatar Dec 16 '15 10:12 Nagarei

operator ですかね・・・。

yumetodo avatar Dec 16 '15 11:12 yumetodo

RGBというクラス名がwindowsのdefineと干渉してしまいました...。 小文字rgbというのもなにか違うような気がしますし...。 どうしましょう?

Nagarei avatar Dec 24 '15 09:12 Nagarei

  1. Put it into a namespace
  2. Prefix with "dle"(e.g. dleRGB)

MaverickTse avatar Dec 24 '15 10:12 MaverickTse

COLORREF型を作るのに一般に用いられるRGBマクロと競合することを見越して

#1

では小文字にしていたんですが。

それが嫌ならいっそ全部PIXEL_から全て始まるようにするとか。

yumetodo avatar Dec 24 '15 11:12 yumetodo

yumetodo なるほど。それで#1では小文字だったのか...。

言い出しっぺが言うのもなんですが、先に #9 でクラス名の命名規則を決めたほうが良いと思いました。 他のライブラリと名前が衝突した場合の対処も考えないといけませんね...。

Nagarei avatar Dec 24 '15 12:12 Nagarei

color_castつくるにせよ、共通関数をつくるにせよあったほうが便利だと思うので、色関係クラスは例えばdxle::color_baseを継承するようにしたほうがいい気がしますがどうでしょう?

yumetodo avatar Dec 28 '15 14:12 yumetodo

https://github.com/MaverickTse/MPUtl/issues/12 なんか似たような話が始まりかけてるな・・・

yumetodo avatar Jan 04 '16 12:01 yumetodo

これってどうなっていますか?

とりあえず見ていて思った疑問ですが、

  • dxle::color::dx_color クラスって今get関数がありますが、いっそunsigned intへの暗黙の型変換を許してもいいんじゃないか?
  • dx_color_paramクラスはなにをするものでしょうか?
  • rgbクラスのrgb_value_t型は実質int型ですが、わざわざ構造体を作った理由は?そしてsignedな理由は?
  • 0-255のデータをintであつかうのはどうなんでしょうか?
  • C#でいうとそれを参考に作っていますか?(URLください)

私がじっくりコーディングできるのは2月中旬に入ってからになりそうですが、とりあえず疑問を書いておかないと2月になっても作業できないので。

yumetodo avatar Jan 27 '16 15:01 yumetodo

color_base

(一か月前のですが...)共通するメンバ関数がないので、空クラスにしかできないと思いますが、どのようなものを想定していますか?

dx_color クラスのunsigned intへの暗黙の型変換

「間違えて座標を引数にすべきところに色を入れてしまった」といったケースをエラーにしたいので、やりたくないです。

dx_color_paramクラス

コメントのサンプルが全てです。 color系クラスを引数にとってDxLibに転送するためのutilityです。なので、dx_colorに変換可能な型から暗黙にコンストラクトできる代わりに、不可逆にしてあります。

0-255のデータをintであつかうのはどうなんでしょうか?

これは整数演算ならintがメモリアラインメント的に一番良いと思ったからです。僕はこのあたりには疎いので、間違っているかもしれませんが...。

signedな理由は?

特に意識してsignedにした訳ではないです。

rgbクラスのrgb_value_t型 C#でいうとそれを参考に作っていますか?

上でメンバ変数の型をintにしてしまったため、publicのままだと不正な値の代入を許すことになってしまいます。そこで、C#の文法のプロパティみたいなことをできないかと思って作ったのがrgb_value_t型です。 C#で参考にしたのはこれだけです。(というわけで、貼れるURLが無いです)

C#のプロパティ ( @Nagarei はC#を触ったことがないので、下のは完全には正しくない可能性があります)

class C
{
    private int v_;

    //プロパティ
    public int v
    {
        set
        {
            //valueは引数
            Debug.Assert( 0 <= value && value <= 255, "error" );
            v_ = value;
        }
        get
        {
            return v_;
        }
    }
}

class Sample
{
    static void Main()
    {
        C c = new C();
        c.v = 0;//OK setが呼ばれる
        int a = c.v;//OK getが呼ばれる
        c.v = -1;//error setが呼ばれ、assertに引っかかる <- これがやりたかった
    }
}

Nagarei avatar Jan 28 '16 10:01 Nagarei

color_base

SFINAEにつかう型制約(concept)に必要なメタクラスが作りやすいかなと。is_colorcastableみたいな。

dx_color クラスのunsigned intへの暗黙の型変換

なるほど・・・。

メモリアラインメント的に

だれか詳しそうな人を探したい、深刻に。

C#のプロパティ

C++17に提案されているOpaque Typedefs(N3515, N3741, P0109R0)とかNamed Types(P0027R0)みたいな機能がC#にもあるのか。

yumetodo avatar Jan 28 '16 12:01 yumetodo

現在の実装だとrgbの引数に大きすぎたり、小さすぎたりする値を入れられたときはassertしていますが、 これは丸めたほうが良いのでしょうか? (負数のときは0、256以上のときは255にする)

Nagarei avatar Feb 23 '16 11:02 Nagarei

いや、assertでいいと思います。見えない挙動が増えるのは良くないので。

yumetodo avatar Feb 23 '16 13:02 yumetodo