sfml3.rb

Class: SFML::Image

Inherits:
Object
  • Object
show all
Defined in:
ext/graphics/image.c,
ext/graphics/image.c

Overview

A 2D array of RGBA pixels, held in RAM (as opposed to Texture, which is GPU-side). Used for loading, editing and saving raw pixel data.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#new(size) ⇒ Image

Creates a black, fully-opaque image of the given size. size is a Vector2 or 2-element Array.

Raises:

  • (RuntimeError) —

    if the image cannot be created



54
55
56
57
58
59
60
61
62
63
64
# File 'ext/graphics/image.c', line 54

static VALUE Image_initialize(VALUE self, VALUE rb_size) {
    sfImage* image = sfImage_create(vec2u_from_rb(rb_size));

    if (image == NULL) {
        rb_raise(rb_eRuntimeError, "failed to create image");
    }

    DATA_PTR(self) = image;

    return self;
}

Class Method Details

.from_color(size, color) ⇒ Image

Creates an image of the given size filled with color.

Returns:

Returns:

Raises:

  • (RuntimeError) —

    if the image cannot be created



74
75
76
77
# File 'ext/graphics/image.c', line 74

static VALUE Image_from_color(VALUE klass, VALUE rb_size, VALUE rb_color) {
    return Image_wrap(klass,
                      sfImage_createFromColor(vec2u_from_rb(rb_size), color_from_rb(rb_color)));
}

.from_file(path) ⇒ Image

Loads an image from the image file at filename.

Returns:

Returns:

Raises:

  • (RuntimeError) —

    if the file cannot be loaded



124
125
126
# File 'ext/graphics/image.c', line 124

static VALUE Image_from_file(VALUE klass, VALUE rb_path) {
    return Image_wrap(klass, sfImage_createFromFile(StringValueCStr(rb_path)));
}

.from_memory(data) ⇒ Image

Loads an image from an in-memory image buffer.

Returns:

Returns:

Raises:

  • (RuntimeError) —

    if the image data cannot be decoded



136
137
138
139
140
141
# File 'ext/graphics/image.c', line 136

static VALUE Image_from_memory(VALUE klass, VALUE rb_data) {
    StringValue(rb_data);

    return Image_wrap(klass,
                      sfImage_createFromMemory(RSTRING_PTR(rb_data), (size_t)RSTRING_LEN(rb_data)));
}

.from_pixels(size, pixels) ⇒ Image

pixels is a String of raw RGBA bytes, at least width * height * 4 bytes long.

Returns:

Returns:

Raises:

  • (ArgumentError) —

    if pixels is shorter than required

  • (RuntimeError) —

    if the image cannot be created



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'ext/graphics/image.c', line 89

static VALUE Image_from_pixels(VALUE klass, VALUE rb_size, VALUE rb_pixels) {
    sfVector2u size = vec2u_from_rb(rb_size);
    size_t expected;
    sfImage* image;

    /* size.x * size.y * 4 as a bare size_t multiplication can wrap on the
       32-bit targets this gem ships, e.g. size.x = size.y = 32768: the true
       product overflows to 0, which would then pass the length check below
       for any input (even an empty string) and hand CSFML a declared size
       far larger than the buffer actually backing it. Check before
       multiplying rather than after. */
    if (size.x != 0 && size.y > (SIZE_MAX / 4) / size.x) {
        rb_raise(rb_eArgError, "image dimensions too large");
    }
    expected = (size_t)size.x * size.y * 4;

    StringValue(rb_pixels);

    if ((size_t)RSTRING_LEN(rb_pixels) < expected) {
        rb_raise(rb_eArgError, "pixel data too short: expected %lu bytes", (unsigned long)expected);
    }

    image = sfImage_createFromPixels(size, (const uint8_t*)RSTRING_PTR(rb_pixels));

    return Image_wrap(klass, image);
}

.from_stream(stream) ⇒ Image

stream is any object responding to the InputStream protocol (see InputStream).

Returns:

Returns:

Raises:

  • (RuntimeError) —

    if the image cannot be loaded



152
153
154
155
156
157
158
159
# File 'ext/graphics/image.c', line 152

static VALUE Image_from_stream(VALUE klass, VALUE rb_stream) {
    VALUE holder = Qnil;
    sfInputStream* stream = input_stream_from_rb(rb_stream, &holder);

    (void)holder;

    return Image_wrap(klass, sfImage_createFromStream(stream));
}

Instance Method Details

#copy ⇒ Image

Returns a deep copy of the object.

Returns:

Returns:

  • (Image) —

    an independent copy



167
168
169
# File 'ext/graphics/image.c', line 167

static VALUE Image_copy(VALUE self) {
    return Image_wrap(Get_Klass_Image(), sfImage_copy(Get_Image_Struct(self)));
}

#copy_image(source, dest, source_rect = Rect.new, apply_alpha = true) ⇒ Boolean

Copies pixels from source (an Image) onto self at position dest. source_rect restricts the copied region; an empty/zero rect copies the whole source image.

Returns:

  • (Boolean)

Returns:

  • (Boolean) —

    whether the copy succeeded



242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'ext/graphics/image.c', line 242

static VALUE Image_copy_image(int argc, VALUE* argv, VALUE self) {
    VALUE rb_source, rb_dest, rb_source_rect, rb_apply_alpha;
    bool apply_alpha = true;

    rb_scan_args(argc, argv, "31", &rb_source, &rb_dest, &rb_source_rect, &rb_apply_alpha);

    if (!rb_obj_is_kind_of(rb_source, rb_cImage)) {
        raise_invalid_argument_class(rb_cImage);
    }

    if (!NIL_P(rb_apply_alpha)) {
        apply_alpha = RTEST(rb_apply_alpha);
    }

    return BOOL2RB(sfImage_copyImage((sfImage*)Get_Image_Struct(self), Get_Image_Struct(rb_source),
                                     vec2u_from_rb(rb_dest), int_rect_from_rb(rb_source_rect),
                                     apply_alpha));
}

#create_mask_from_color(color, alpha) ⇒ self

Sets the alpha channel of every pixel matching color to alpha.

Returns:

  • (self)

Returns:

  • (self)


227
228
229
230
231
# File 'ext/graphics/image.c', line 227

static VALUE Image_create_mask_from_color(VALUE self, VALUE rb_color, VALUE rb_alpha) {
    sfImage_createMaskFromColor((sfImage*)Get_Image_Struct(self), color_from_rb(rb_color),
                                (uint8_t)NUM2INT(rb_alpha));
    return self;
}

#flip_horizontally! ⇒ self

Flips the image horizontally.

Returns:

  • (self)

Returns:

  • (self)


312
313
314
315
# File 'ext/graphics/image.c', line 312

static VALUE Image_flip_horizontally(VALUE self) {
    sfImage_flipHorizontally((sfImage*)Get_Image_Struct(self));
    return self;
}

#flip_vertically! ⇒ self

Flips the image vertically.

Returns:

  • (self)

Returns:

  • (self)


323
324
325
326
# File 'ext/graphics/image.c', line 323

static VALUE Image_flip_vertically(VALUE self) {
    sfImage_flipVertically((sfImage*)Get_Image_Struct(self));
    return self;
}

#pixel(x, y) ⇒ Color

Returns the color of the pixel at x, y.

Returns:

Returns:

  • (Color) —

    the color of the pixel at (+x+, y)



267
268
269
270
271
272
# File 'ext/graphics/image.c', line 267

static VALUE Image_get_pixel(VALUE self, VALUE rb_x, VALUE rb_y) {
    sfColor color = sfImage_getPixel(
        Get_Image_Struct(self), (sfVector2u){(unsigned)NUM2UINT(rb_x), (unsigned)NUM2UINT(rb_y)});

    return color_to_rb(color);
}

#pixels ⇒ String

Returns a flat array of the image's pixels.

Returns:

  • (String)

Returns:

  • (String) —

    the raw RGBA pixel data, width * height * 4 bytes, row-major starting from the top-left



294
295
296
297
298
299
300
301
302
303
304
# File 'ext/graphics/image.c', line 294

static VALUE Image_get_pixels(VALUE self) {
    const sfImage* image = Get_Image_Struct(self);
    sfVector2u size = sfImage_getSize(image);
    const uint8_t* pixels = sfImage_getPixelsPtr(image);

    if (pixels == NULL) {
        return rb_str_new("", 0);
    }

    return rb_str_new((const char*)pixels, (long)(size.x * size.y * 4));
}

#save_to_file(path) ⇒ Boolean

The format is deduced from +path+'s extension.

Returns:

  • (Boolean)

Returns:

  • (Boolean) —

    whether the save succeeded



188
189
190
# File 'ext/graphics/image.c', line 188

static VALUE Image_save_to_file(VALUE self, VALUE rb_path) {
    return BOOL2RB(sfImage_saveToFile(Get_Image_Struct(self), StringValueCStr(rb_path)));
}

#save_to_memory(format = "png") ⇒ Buffer?

format is an image file extension without the dot (e.g. "png", "bmp", "tga", "jpg").

Returns:

Returns:

  • (Buffer, nil) —

    the encoded image data, or nil if encoding failed

Raises:

  • (ArgumentError) —

    if given more than one argument



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'ext/graphics/image.c', line 201

static VALUE Image_save_to_memory(int argc, VALUE* argv, VALUE self) {
    VALUE rb_buffer;
    const char* format = "png";
    if (argc > 1) {
        raise_invalid_arguments_excepted(1, argc);
    }

    if (argc == 1 && !NIL_P(argv[0])) {
        format = StringValueCStr(argv[0]);
    }

    rb_buffer = rb_funcall(Get_Klass_Buffer(), rb_intern("new"), 0);

    if (sfImage_saveToMemory(Get_Image_Struct(self), Get_Buffer_Struct(rb_buffer), format)) {
        return rb_buffer;
    }

    return Qnil;
}

#set_pixel(x, y, color) ⇒ self

Sets the color of the pixel at x, y.

Returns:

  • (self)

Returns:

  • (self)


280
281
282
283
284
285
# File 'ext/graphics/image.c', line 280

static VALUE Image_set_pixel(VALUE self, VALUE rb_x, VALUE rb_y, VALUE rb_color) {
    sfImage_setPixel((sfImage*)Get_Image_Struct(self),
                     (sfVector2u){(unsigned)NUM2UINT(rb_x), (unsigned)NUM2UINT(rb_y)},
                     color_from_rb(rb_color));
    return self;
}

#size ⇒ Vector2

Returns the object's size.

Returns:

Returns:

  • (Vector2) —

    the image's dimensions in pixels



177
178
179
180
# File 'ext/graphics/image.c', line 177

static VALUE Image_get_size(VALUE self) {
    return vec2f_to_rb((sfVector2f){(float)sfImage_getSize(Get_Image_Struct(self)).x,
                                    (float)sfImage_getSize(Get_Image_Struct(self)).y});
}