Class: Rixmap::Image::Line

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
src/rixmapcore.cxx,
src/rixmapcore.cxx

Overview

TODO:

文字列からレイアウトに沿って更新するメソッド (#to_s の逆) の実装

スキャンラインクラス.

Instance Method Summary collapse

Constructor Details

#initialize(argImage, argLineNumber) (private)

スキャンラインオブジェクトを初期化します.

Parameters:

  • image (Rixmap::Image)

    参照先画像

  • lineno (Integer)

    参照先行番号



2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
# File 'src/rixmapcore.cxx', line 2913

static VALUE ImageLine_initialize(VALUE self, VALUE argImage, VALUE argLineNumber) {
    // 引数のチェック
    if (!RTEST(rb_obj_is_kind_of(argImage, cRixmapImage))) {
        rb_raise(rb_eArgError, "parent image expected %s, but %s", rb_class2name(argImage), rb_obj_classname(argImage));
    }
    int32_t lineno = NUM2LONG(rb_Integer(argLineNumber));

    // データを初期化
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    _this->setImage(argImage);
    _this->setLineNumber(lineno);

    return self;
}

Instance Method Details

#[](argOffset) ⇒ Integer, ...

スキャンライン内の指定位置のピクセルデータを取得します.

ピクセルデータの形式は Rixmap::Image#[] を参照してください.

Parameters:

  • offset (Integer)

    取得オフセット

Returns:

  • (Integer, Array, nil)

    ピクセルデータ

See Also:



3109
3110
3111
3112
3113
3114
# File 'src/rixmapcore.cxx', line 3109

static VALUE ImageLine_offsetGet(VALUE self, VALUE argOffset) {
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    long offset = NUM2LONG(rb_Integer(argOffset));

    return Rixmap::Helper::GetPixel(_this->getImageData(), offset, _this->getLineNumber());
}

#[]=(argOffset, argColor)

This method returns an undefined value.

スキャンライン内の指定位置のピクセルデータを更新します.

ピクセルデータの形式は Rixmap::Image#[]= を参照してください.

Parameters:

  • offset (Integer)

    更新オフセット

  • color (Integer, Array, Rixmap::Color)

    更新データ

See Also:



3126
3127
3128
3129
3130
3131
3132
3133
# File 'src/rixmapcore.cxx', line 3126

static VALUE ImageLine_offsetSet(VALUE self, VALUE argOffset, VALUE argColor) {
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    long offset = NUM2LONG(rb_Integer(argOffset));

    Rixmap::Helper::UpdatePixel(_this->getImageData(), offset, _this->getLineNumber(), argColor);

    return argColor;
}

#alphaArray<Integer>

スキャンライン内のピクセルデータの、透明度のみのバイトデータを配列で取得します. 透明度チャンネルを持たない場合や、スキャンラインが無効な場合はnilを返します.

Returns:

  • (Array<Integer>)

    透明度のみのバイトデータ.



3037
3038
3039
3040
# File 'src/rixmapcore.cxx', line 3037

static VALUE ImageLine_getAlphaBand(VALUE self) {
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    return Rixmap::Helper::GetBand(_this, Rixmap::Channel::ALPHA);
}

#alpha=(argBand)

This method returns an undefined value.

スキャンライン内のピクセルデータの、透明度のみを更新します.

Parameters:

  • band (String, Array)

    更新データ



3048
3049
3050
3051
3052
# File 'src/rixmapcore.cxx', line 3048

static VALUE ImageLine_setAlphaBand(VALUE self, VALUE argBand) {
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    Rixmap::Helper::UpdateBand(_this, Rixmap::Channel::ALPHA, argBand);
    return argBand;
}

#blueArray<Integer>

スキャンライン内のピクセルデータの、青要素のみのバイトデータを配列で取得します. 青要素チャンネルを持たない場合や、スキャンラインが無効な場合はnilを返します.

Returns:

  • (Array<Integer>)

    青要素のみのバイトデータ.



3014
3015
3016
3017
# File 'src/rixmapcore.cxx', line 3014

static VALUE ImageLine_getBlueBand(VALUE self) {
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    return Rixmap::Helper::GetBand(_this, Rixmap::Channel::BLUE);
}

#blue=(argBand)

This method returns an undefined value.

スキャンライン内のピクセルデータの、青要素のみを更新します.

Parameters:

  • band (String, Array)

    更新データ



3025
3026
3027
3028
3029
# File 'src/rixmapcore.cxx', line 3025

static VALUE ImageLine_setBlueBand(VALUE self, VALUE argBand) {
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    Rixmap::Helper::UpdateBand(_this, Rixmap::Channel::BLUE, argBand);
    return argBand;
}

#eachEnumerator #each {|pixel| ... } ⇒ Rixmap::ImageLine

スキャンライン内の各ピクセルを走査するイテレータを返します. ブロックが渡されている場合はイテレータを返す代わりに、各ピクセルデータを引数として ブロックを呼び出します.

Overloads:

  • #eachEnumerator

    ブロックが渡されていない場合はピクセル走査用イテレータを返します.

    Returns:

    • (Enumerator)

      ピクセル走査用イテレータ

  • #each {|pixel| ... } ⇒ Rixmap::ImageLine

    ブロックが渡されている場合は各ピクセルデータを引数として、渡されたブロックを呼び出します. 戻り値はこのスキャンラインオブジェクトになります.

    Yields:

    • (pixel)

      ピクセルを引数として呼び出します.

    Yield Parameters:

    • pixel (Integer, Array)

      ピクセルデータ

    Returns:

    • (Rixmap::ImageLine)

      self自身を返します.



3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
# File 'src/rixmapcore.cxx', line 3265

static VALUE ImageLine_each(VALUE self) {
    if (rb_block_given_p()) {       // ブロック有り
        Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
        if (_this->isValid()) {
            Rixmap::ImageData* _parent = _this->getImageData();
            int32_t length = _this->getLength();
            int32_t lineno = _this->getLineNumber();
            for (int32_t i = 0; i < length; i++) {
                VALUE pixel = Rixmap::Helper::GetPixel(_parent, i, lineno);
                rb_yield_values(1, pixel);
            }
        }
        return self;
    } else {                        // ブロック無し
        // TODO サイズ計算関数の追加
        //      その時は rb_enumeratorize_with_sizeを使おう
        //      (RETURN_SIZED_ENUMERATORでもいいかも)
        return rb_enumeratorize(self, ID2SYM(rb_frame_this_func()), 0, NULL);
    }
}

#greenArray<Integer>

スキャンライン内のピクセルデータの、緑要素のみのバイトデータを配列で取得します. 緑要素チャンネルを持たない場合や、スキャンラインが無効な場合はnilを返します.

Returns:

  • (Array<Integer>)

    緑要素のみのバイトデータ.



2991
2992
2993
2994
# File 'src/rixmapcore.cxx', line 2991

static VALUE ImageLine_getGreenBand(VALUE self) {
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    return Rixmap::Helper::GetBand(_this, Rixmap::Channel::GREEN);
}

#green=(argBand)

This method returns an undefined value.

スキャンライン内のピクセルデータの、緑要素のみを更新します.

Parameters:

  • band (String, Array)

    更新データ



3002
3003
3004
3005
3006
# File 'src/rixmapcore.cxx', line 3002

static VALUE ImageLine_setGreenBand(VALUE self, VALUE argBand) {
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    Rixmap::Helper::UpdateBand(_this, Rixmap::Channel::GREEN, argBand);
    return argBand;
}

#imageRixmap::Image

参照先の親画像を返します.

Returns:



2933
2934
2935
2936
# File 'src/rixmapcore.cxx', line 2933

static VALUE ImageLine_getImage(VALUE self) {
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    return _this->getImage();
}

#inspectString

オブジェクトとしての文字列表現を返します.

Returns:

  • (String)

    文字列表現



3319
3320
3321
3322
3323
3324
3325
3326
3327
# File 'src/rixmapcore.cxx', line 3319

static VALUE ImageLine_inspect(VALUE self) {
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    VALUE imageText = rb_inspect(_this->getImage());
    return rb_enc_sprintf(
            rb_usascii_encoding(),
            "#<%s:%p image=%s, lineno=%d>",
            rb_obj_classname(self), reinterpret_cast<void*>(self),
            StringValueCStr(imageText), _this->getLineNumber());
}

#linenoInteger

参照先の行番号を返します.

Returns:

  • (Integer)

    行番号



2943
2944
2945
2946
# File 'src/rixmapcore.cxx', line 2943

static VALUE ImageLine_getLineNumber(VALUE self) {
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    return LONG2NUM(_this->getLineNumber());
}

#luminanceArray<Integer>

スキャンライン内のピクセルデータの、輝度値のみのバイトデータを配列で取得します. 輝度値チャンネルを持たない場合や、スキャンラインが無効な場合はnilを返します.

Returns:

  • (Array<Integer>)

    輝度値のみのバイトデータ.



3060
3061
3062
3063
# File 'src/rixmapcore.cxx', line 3060

static VALUE ImageLine_getLuminanceBand(VALUE self) {
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    return Rixmap::Helper::GetBand(_this, Rixmap::Channel::LUMINANCE);
}

#luminance=(argBand)

This method returns an undefined value.

スキャンライン内のピクセルデータの、輝度値のみを更新します.

Parameters:

  • band (String, Array)

    更新データ



3071
3072
3073
3074
3075
# File 'src/rixmapcore.cxx', line 3071

static VALUE ImageLine_setLuminanceBand(VALUE self, VALUE argBand) {
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    Rixmap::Helper::UpdateBand(_this, Rixmap::Channel::LUMINANCE, argBand);
    return argBand;
}

#map! {|pixel| ... } ⇒ Rixmap::Image::Line

スキャンライン内の各ピクセルについてブロックを呼び出し、その戻り値でピクセルを更新します.

Returns selfを返します.

Yields:

  • (pixel)

    ピクセルごとにブロックを呼び出します.

Yield Parameters:

  • pixel (Integer, Array)

    ピクセルデータ

Returns:



3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
# File 'src/rixmapcore.cxx', line 3294

static VALUE ImageLine_mapSelf(VALUE self) {
    if (!rb_block_given_p()) {
        rb_raise(rb_eRuntimeError, "block parameter are required.");
    }

    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    if (_this->isValid()) {
        Rixmap::ImageData* _parent = _this->getImageData();
        int32_t length = _this->getLength();
        int32_t lineno = _this->getLineNumber();
        for (int32_t i = 0; i < length; i++) {
            VALUE pixel = Rixmap::Helper::GetPixel(_parent, i, lineno);
            VALUE resp  = rb_yield_values(1, pixel);
            Rixmap::Helper::UpdatePixel(_parent, i, lineno, resp);
        }
    }

    return self;
}

#paletteArray<Integer>

スキャンライン内のピクセルデータの、パレットインデックスのみのバイトデータを配列で取得します. パレットインデックスチャンネルを持たない場合や、スキャンラインが無効な場合はnilを返します.

Returns:

  • (Array<Integer>)

    パレットインデックスのみのバイトデータ.



3083
3084
3085
3086
# File 'src/rixmapcore.cxx', line 3083

static VALUE ImageLine_getPaletteBand(VALUE self) {
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    return Rixmap::Helper::GetBand(_this, Rixmap::Channel::PALETTE);
}

#palette=(argBand)

This method returns an undefined value.

スキャンライン内のピクセルデータの、パレットインデックスのみを更新します.

Parameters:

  • band (String, Array)

    更新データ



3094
3095
3096
3097
3098
# File 'src/rixmapcore.cxx', line 3094

static VALUE ImageLine_setPaletteBand(VALUE self, VALUE argBand) {
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    Rixmap::Helper::UpdateBand(_this, Rixmap::Channel::PALETTE, argBand);
    return argBand;
}

#redArray<Integer>

スキャンライン内のピクセルデータの、赤要素のみのバイトデータを配列で取得します. 赤要素チャンネルを持たない場合や、スキャンラインが無効な場合はnilを返します.

Returns:

  • (Array<Integer>)

    赤要素のみのバイトデータ.



2968
2969
2970
2971
# File 'src/rixmapcore.cxx', line 2968

static VALUE ImageLine_getRedBand(VALUE self) {
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    return Rixmap::Helper::GetBand(_this, Rixmap::Channel::RED);
}

#red=(argBand)

This method returns an undefined value.

スキャンライン内のピクセルデータの、赤要素のみを更新します.

Parameters:

  • band (String, Array)

    更新データ



2979
2980
2981
2982
2983
# File 'src/rixmapcore.cxx', line 2979

static VALUE ImageLine_setRedBand(VALUE self, VALUE argBand) {
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    Rixmap::Helper::UpdateBand(_this, Rixmap::Channel::RED, argBand);
    return argBand;
}

#to_aArray?

スキャンライン内のピクセルデータを配列で返します.

Examples:

rgb = Rixmap::Image.new('RGB', 32, 32)
rgb[0].to_a        #=> [[0, 0, 0], [0, 0, 0], ...]

idx = Rixmap::Image.new('INDEXED', 32, 32)
idx[0].to_a        #=> [0, 0, 0, ...]

Returns:

  • (Array, nil)

    ピクセルデータの配列. スキャンライン自体が無効な場合はnilになります.



3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
# File 'src/rixmapcore.cxx', line 3146

static VALUE ImageLine_toArray(VALUE self) {
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    if (_this->isValid()) {
        Rixmap::ImageData* _parent = _this->getImageData();
        int32_t length = _this->getLength();
        int32_t lineno = _this->getLineNumber();
        VALUE pixels = rb_ary_new2(length);
        for (int32_t i = 0; i < length; i++) {
            VALUE pixel = Rixmap::Helper::GetPixel(_parent, i, lineno);
            rb_ary_store(pixels, i, pixel);
        }
        return pixels;
    } else {
        return Qnil;
    }
}

#to_s(layout = nil) ⇒ Object

スキャンラインのピクセルデータを格納した文字列データ (バイト列データ) を返します.

Examples:

rgb = Rixmap::Image.new('RGB', 32, 32)
rgb[0].to_s        #=> 96バイト
rgb[1].to_s('L')   #=> 0バイト (チャンネルを含まないため)
rgb[2].to_s('R')   #=> 32バイト (赤要素のみ)

ピクセルデータをバイト列として取得します. レイアウトが指定されている場合は、対応するチャンネル毎に並べなおします. レイアウトが指定されていない場合はバイト列をすべて格納していきます. その時、RGB(A)形式はR-G-B(-A)の順に並び、GRAYALPHA形式も同様に透明度が後ろになります.

Parameters:

  • layout (String, Symbol, Array) (defaults to: nil)

    各ピクセルの並び順. 使用可能なものは 'R', 'G', 'B', 'A', 'L', 'P' です. 指定されたチャンネルを持たない画像の場合は、その部分は欠落します.

See Also:

  • Palette#to_s


3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
# File 'src/rixmapcore.cxx', line 3180

static VALUE ImageLine_toString(int argc, VALUE* argv, VALUE self) {
    // 引数解析
    VALUE argLayout = Qnil;
    rb_scan_args(argc, argv, "01", &argLayout);

    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    Rixmap::CharBuffer bytes;

    // 有効かどうかを判定
    if (_this->isValid()) {
        Rixmap::ImageData* _parent = _this->getImageData();
        int32_t length = _this->getLength();
        int32_t lineno = _this->getLineNumber();
        const Rixmap::ModeInfo& mode = _parent->getModeInfo();
        const Rixmap::ChannelArray& channels = mode.getChannels();

        // 対象チャンネルを保存
        std::vector<Rixmap::Channel> layout;
        if (NIL_P(argLayout)) {
            // 無指定の場合はチャンネルデータをすべて有効化
            for (auto it = channels.begin(); it != channels.end(); it++) {
                layout.push_back(*it);
            }
        } else {
            // 指定されている場合は解析する
            // TODO パレットのほうと共通化
            if (RB_TYPE_P(argLayout, T_ARRAY)) {
                long arylen = RARRAY_LEN(argLayout);
                for (long i = 0; i < arylen; i++) {
                    VALUE item = rb_String(rb_ary_entry(argLayout, i));
                    item = rb_funcall(item, rb_intern("upcase"), 0);
                    long  slen = RSTRING_LEN(item);
                    char* sptr = StringValuePtr(item);
                    if (slen > 0) {
                        // 先頭文字を入れる
                        Rixmap::Channel ch = static_cast<Rixmap::Channel>(sptr[0]);
                        if (mode.has(ch)) {
                            // 対応している場合のみ
                            layout.push_back(ch);
                        }
                    }
                }
            } else {
                // 文字列にして各バイトで入れ込む
                VALUE objLayout = rb_funcall(rb_String(argLayout), rb_intern("upcase"), 0);
                long  slen = RSTRING_LEN(objLayout);
                char* sptr = StringValuePtr(objLayout);
                for (long i = 0; i < slen; i++) {
                    Rixmap::Channel ch = static_cast<Rixmap::Channel>(sptr[i]);
                    if (mode.has(ch)) {
                        layout.push_back(ch);
                    }
                }
            }
        }

        // 各チャンネル毎にバイトとして追加
        for (int32_t i = 0; i < length; i++) {
            for (auto it = layout.begin(); it != layout.end(); it++) {
                Rixmap::Channel ch = *it;
                bytes.push_back(_parent->get(ch, i, lineno));
            }
        }
    }

    // 文字列化
    return rb_enc_str_new(bytes.data(), bytes.size(), rb_ascii8bit_encoding());
}

#valid?Boolean

このスキャンラインが有効な画像と行番号への参照になっているかを返します.

Returns:

  • (Boolean)

    有効なスキャンラインオブジェクトならtrue



2953
2954
2955
2956
2957
2958
2959
2960
# File 'src/rixmapcore.cxx', line 2953

static VALUE ImageLine_isValid(VALUE self) {
    Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
    if (_this->isValid()) {
        return Qtrue;
    } else {
        return Qfalse;
    }
}