Class: SFML::Image

Inherits:
Object
  • Object
show all
Defined in:
lib/sfml/graphics/image.rb

Overview

CPU-side bitmap. Lives in main memory and supports per-pixel reads / writes — handy for procedural generation, screenshots, masks, and anything that needs to inspect or modify pixel data before upload.

img = SFML::Image.new(800, 600, fill: SFML::Color.cornflower_blue)
img = SFML::Image.load("assets/hero.png")

img[10, 20] = SFML::Color.red
img[10, 20]                       #=> Color(255, 0, 0, 255)

img.flip_vertically
img.save("out.png")

Convert to a GPU-side texture for drawing:

tex = SFML::Texture.from_image(img)
sprite = SFML::Sprite.new(tex)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(width, height, fill: nil) ⇒ Image

Create a blank image of the given size. With ‘fill:` it’s filled with that colour; without, with transparent black.

Raises:



22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/sfml/graphics/image.rb', line 22

def initialize(width, height, fill: nil)
  size = C::System::Vector2u.new
  size[:x] = Integer(width)
  size[:y] = Integer(height)

  ptr = if fill
          C::Graphics.sfImage_createFromColor(size, fill.to_native)
        else
          C::Graphics.sfImage_create(size)
        end
  raise Error, "sfImage_create returned NULL" if ptr.null?
  _take_ownership(ptr)
end

Instance Attribute Details

#handleObject (readonly)

:nodoc:



187
188
189
# File 'lib/sfml/graphics/image.rb', line 187

def handle
  @handle
end

Class Method Details

.from_memory(bytes) ⇒ Object

Decode an image from a Ruby String of bytes (PNG, JPG, BMP, TGA, GIF, HDR, PSD — whatever stb_image / SFML’s loader supports). Mirror of ‘Image#save_to_memory` for round-trips without touching the disk.

Raises:

  • (ArgumentError)


48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/sfml/graphics/image.rb', line 48

def self.from_memory(bytes)
  raise ArgumentError, "expected a String, got #{bytes.class}" unless bytes.is_a?(String)

  buf = FFI::MemoryPointer.new(:uint8, bytes.bytesize)
  buf.write_bytes(bytes)
  ptr = C::Graphics.sfImage_createFromMemory(buf, bytes.bytesize)
  raise Error, "sfImage_createFromMemory returned NULL — unsupported format?" if ptr.null?

  img = allocate
  img.send(:_take_ownership, ptr)
  img
end

.from_pixels(width, height, pixels) ⇒ Object

Build an image from a raw RGBA byte string. ‘pixels` must be exactly width*height*4 bytes, row-major from the top-left.

Raises:

  • (ArgumentError)


63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/sfml/graphics/image.rb', line 63

def self.from_pixels(width, height, pixels)
  expected = Integer(width) * Integer(height) * 4
  raise ArgumentError, "expected #{expected} bytes, got #{pixels.bytesize}" if pixels.bytesize != expected

  buf = FFI::MemoryPointer.new(:uint8, expected)
  buf.write_bytes(pixels)

  size = C::System::Vector2u.new
  size[:x] = Integer(width)
  size[:y] = Integer(height)
  ptr = C::Graphics.sfImage_createFromPixels(size, buf)
  raise Error, "sfImage_createFromPixels returned NULL" if ptr.null?

  img = allocate
  img.send(:_take_ownership, ptr)
  img
end

.load(path) ⇒ Object

Raises:



36
37
38
39
40
41
42
# File 'lib/sfml/graphics/image.rb', line 36

def self.load(path)
  ptr = C::Graphics.sfImage_createFromFile(path.to_s)
  raise Error, "Could not load image from #{path.inspect}" if ptr.null?
  img = allocate
  img.send(:_take_ownership, ptr)
  img
end

Instance Method Details

#[](x, y) ⇒ Object

Read the colour of a single pixel.



89
90
91
92
93
# File 'lib/sfml/graphics/image.rb', line 89

def [](x, y)
  coord = C::System::Vector2u.new
  coord[:x] = Integer(x); coord[:y] = Integer(y)
  Color.from_native(C::Graphics.sfImage_getPixel(@handle, coord))
end

#[]=(x, y, color) ⇒ Object

Write a single pixel.



96
97
98
99
100
# File 'lib/sfml/graphics/image.rb', line 96

def []=(x, y, color)
  coord = C::System::Vector2u.new
  coord[:x] = Integer(x); coord[:y] = Integer(y)
  C::Graphics.sfImage_setPixel(@handle, coord, color.to_native)
end

#copy_from(source, at:, source_rect: nil, apply_alpha: false) ⇒ Object

Copy a rectangular region of ‘source` into this image. The source region is `source_rect` (a `SFML::Rect` or `[x, y, w, h]` Array; defaults to the entire source); the destination top-left in this image is `at` (`[x, y]`). When `apply_alpha` is true, the source’s alpha channel blends with this image’s existing pixels; otherwise the copy is opaque.

Useful for stamping sprites onto an atlas, blitting one image into a sub-rect of another, or hand-building a composite before uploading to GPU.

Raises:

  • (ArgumentError)


120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/sfml/graphics/image.rb', line 120

def copy_from(source, at:, source_rect: nil, apply_alpha: false)
  raise ArgumentError, "Image#copy_from needs a SFML::Image" unless source.is_a?(Image)

  dest = C::System::Vector2u.new
  dest[:x] = Integer(at[0]); dest[:y] = Integer(at[1])

  sr_struct = C::Graphics::IntRect.new
  x, y, w, h =
    case source_rect
    when nil   then [0, 0, 0, 0]   # zeroes = "entire source" in CSFML
    when Rect  then [source_rect.x, source_rect.y, source_rect.width, source_rect.height]
    when Array then source_rect
    else raise ArgumentError, "source_rect must be a SFML::Rect or [x, y, w, h]"
    end
  sr_struct[:position][:x] = Integer(x); sr_struct[:position][:y] = Integer(y)
  sr_struct[:size][:x]     = Integer(w); sr_struct[:size][:y]     = Integer(h)
  C::Graphics.sfImage_copyImage(@handle, source.handle, dest, sr_struct, !!apply_alpha)
  self
end

#flip_horizontallyObject



177
178
179
180
# File 'lib/sfml/graphics/image.rb', line 177

def flip_horizontally
  C::Graphics.sfImage_flipHorizontally(@handle)
  self
end

#flip_verticallyObject



182
183
184
185
# File 'lib/sfml/graphics/image.rb', line 182

def flip_vertically
  C::Graphics.sfImage_flipVertically(@handle)
  self
end

#heightObject



86
# File 'lib/sfml/graphics/image.rb', line 86

def height = size.y

#mask_color!(color, alpha: 0) ⇒ Object

Replace any pixel matching ‘color` with that colour at `alpha` opacity — typical use is to turn a fixed background colour transparent: img.mask_color!(SFML::Color.magenta, alpha: 0).



172
173
174
175
# File 'lib/sfml/graphics/image.rb', line 172

def mask_color!(color, alpha: 0)
  C::Graphics.sfImage_createMaskFromColor(@handle, color.to_native, Integer(alpha))
  self
end

#pixelsObject

Write the entire pixel buffer back as a Ruby String. Useful for piping to image-processing libraries or writing custom file formats. Format: width*height*4 bytes, RGBA, row-major from top-left.



105
106
107
108
# File 'lib/sfml/graphics/image.rb', line 105

def pixels
  ptr = C::Graphics.sfImage_getPixelsPtr(@handle)
  ptr.read_bytes(width * height * 4)
end

#save(path) ⇒ Object

Raises:



140
141
142
143
144
# File 'lib/sfml/graphics/image.rb', line 140

def save(path)
  ok = C::Graphics.sfImage_saveToFile(@handle, path.to_s)
  raise Error, "Could not save image to #{path.inspect}" unless ok
  path
end

#save_to_memory(format) ⇒ Object

Encode the image as ‘format` (“png”, “jpg”, “bmp”, or “tga”) and return the encoded bytes as a Ruby String. Useful for sending screenshots over the network, generating data: URLs, piping into an image-processing library, etc., without touching the disk.

png_bytes = img.save_to_memory("png")
File.binwrite("out.png", png_bytes)

Raises:



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/sfml/graphics/image.rb', line 153

def save_to_memory(format)
  buffer = C::System.sfBuffer_create
  raise Error, "sfBuffer_create returned NULL" if buffer.null?

  begin
    ok = C::Graphics.sfImage_saveToMemory(@handle, buffer, format.to_s)
    raise Error, "Could not encode image as #{format.inspect}" unless ok

    size = C::System.sfBuffer_getSize(buffer)
    data = C::System.sfBuffer_getData(buffer)
    data.read_bytes(size)
  ensure
    C::System.sfBuffer_destroy(buffer)
  end
end

#sizeObject



81
82
83
# File 'lib/sfml/graphics/image.rb', line 81

def size
  Vector2.from_native(C::Graphics.sfImage_getSize(@handle))
end

#widthObject



85
# File 'lib/sfml/graphics/image.rb', line 85

def width  = size.x