Class: Skia::Image

Inherits:
Base
  • Object
show all
Defined in:
lib/skia/image.rb

Instance Attribute Summary

Attributes inherited from Base

#ptr

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#null?, release_callback, #to_ptr

Constructor Details

#initialize(ptr) ⇒ Image

Returns a new instance of Image.



5
6
7
# File 'lib/skia/image.rb', line 5

def initialize(ptr)
  super(ptr, :sk_image_unref)
end

Class Method Details

.from_bitmap(bitmap) ⇒ Object

Raises:

  • (ArgumentError)


25
26
27
28
29
30
31
32
# File 'lib/skia/image.rb', line 25

def self.from_bitmap(bitmap)
  raise ArgumentError, 'bitmap must be a Skia::Bitmap' unless bitmap.is_a?(Bitmap)

  ptr = Native.sk_image_new_from_bitmap(bitmap.ptr)
  raise DecodingError, 'Failed to create image from bitmap' if ptr.nil? || ptr.null?

  new(ptr)
end

.from_data(data) ⇒ Object

Raises:



17
18
19
20
21
22
23
# File 'lib/skia/image.rb', line 17

def self.from_data(data)
  data_obj = data.is_a?(Data) ? data : Data.new(data)
  ptr = Native.sk_image_new_from_encoded(data_obj.ptr)
  raise DecodingError, 'Failed to decode image data' if ptr.nil? || ptr.null?

  new(ptr)
end

.from_file(path) ⇒ Object

Raises:



9
10
11
12
13
14
15
# File 'lib/skia/image.rb', line 9

def self.from_file(path)
  data = Data.from_file(path)
  ptr = Native.sk_image_new_from_encoded(data.ptr)
  raise DecodingError, "Failed to decode image: #{path}" if ptr.nil? || ptr.null?

  new(ptr)
end

Instance Method Details

#alpha_typeObject



50
51
52
# File 'lib/skia/image.rb', line 50

def alpha_type
  Native.sk_image_get_alpha_type(@ptr)
end

#color_spaceObject



54
55
56
# File 'lib/skia/image.rb', line 54

def color_space
  ColorSpace.wrap(Native.sk_image_get_colorspace(@ptr), retain: true)
end

#color_typeObject



46
47
48
# File 'lib/skia/image.rb', line 46

def color_type
  Native.sk_image_get_color_type(@ptr)
end

#encode(format = :png, quality = 100) ⇒ Object

Raises:



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/skia/image.rb', line 116

def encode(format = :png, quality = 100)
  # Create a pixmap to hold the image pixels
  pixmap = Native.sk_pixmap_new
  raise EncodingError, 'Failed to create pixmap' if pixmap.nil? || pixmap.null?

  begin
    # Peek pixels from the image into the pixmap
    raise EncodingError, 'Failed to peek pixels from image' unless Native.sk_image_peek_pixels(@ptr, pixmap)

    stream = Native.sk_dynamicmemorywstream_new
    raise EncodingError, 'Failed to create stream' if stream.nil? || stream.null?

    begin
      success = case format
                when :png
                  options = Native::SKPngEncoderOptions.new
                  options[:fFilterFlags] = :all
                  options[:fZLibLevel] = 6
                  options[:fComments] = nil
                  options[:fICCProfile] = nil
                  options[:fICCProfileDescription] = nil
                  Native.sk_pngencoder_encode(stream, pixmap, options)
                when :jpeg, :jpg
                  options = Native::SKJpegEncoderOptions.new
                  options[:fQuality] = quality
                  options[:fDownsample] = :downsample_420
                  options[:fAlphaOption] = :ignore
                  options[:xmpMetadata] = nil
                  options[:fICCProfile] = nil
                  options[:fICCProfileDescription] = nil
                  Native.sk_jpegencoder_encode(stream, pixmap, options)
                when :webp
                  options = Native::SKWebpEncoderOptions.new
                  options[:fCompression] = :lossy
                  options[:fQuality] = quality.to_f
                  options[:fICCProfile] = nil
                  options[:fICCProfileDescription] = nil
                  Native.sk_webpencoder_encode(stream, pixmap, options)
                else
                  options = Native::SKPngEncoderOptions.new
                  options[:fFilterFlags] = :all
                  options[:fZLibLevel] = 6
                  options[:fComments] = nil
                  options[:fICCProfile] = nil
                  options[:fICCProfileDescription] = nil
                  Native.sk_pngencoder_encode(stream, pixmap, options)
                end

      raise EncodingError, "Failed to encode image as #{format}" unless success

      data_ptr = Native.sk_dynamicmemorywstream_detach_as_data(stream)
      raise EncodingError, 'Failed to get encoded data' if data_ptr.nil? || data_ptr.null?

      Data.new(data_ptr)
    ensure
      Native.sk_dynamicmemorywstream_destroy(stream)
    end
  ensure
    Native.sk_pixmap_destructor(pixmap)
  end
end

#encoded_dataObject



58
59
60
61
62
63
# File 'lib/skia/image.rb', line 58

def encoded_data
  ptr = Native.sk_image_ref_encoded(@ptr)
  return encode(:png) if ptr.nil? || ptr.null?

  Data.new(ptr)
end

#heightObject



38
39
40
# File 'lib/skia/image.rb', line 38

def height
  Native.sk_image_get_height(@ptr)
end

#make_shader(tile_x: :clamp, tile_y: :clamp, matrix: nil) ⇒ Object

Raises:



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

def make_shader(tile_x: :clamp, tile_y: :clamp, matrix: nil)
  matrix_struct = matrix&.to_struct
  sampling = Native::SKSamplingOptions.new
  sampling[:fMaxAniso] = 0
  sampling[:fUseCubic] = 0
  sampling[:fCubicB] = 0.0
  sampling[:fCubicC] = 0.0
  sampling[:fFilter] = :nearest
  sampling[:fMipmap] = :none

  ptr = Native.sk_image_make_shader(@ptr, tile_x, tile_y, sampling, matrix_struct)
  raise Error, 'Failed to create shader from image' if ptr.nil? || ptr.null?

  Shader.new(ptr)
end

#peek_pixelsObject



109
110
111
112
113
114
# File 'lib/skia/image.rb', line 109

def peek_pixels
  pixmap = Pixmap.new
  return nil unless Native.sk_image_peek_pixels(@ptr, pixmap.ptr)

  pixmap
end

#read_pixels(width: nil, height: nil, src_x: 0, src_y: 0, row_bytes: nil, image_info: nil, color_type: :rgba_8888, alpha_type: :premul, color_space: nil, caching_hint: :allow) ⇒ Object

Raises:



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/skia/image.rb', line 89

def read_pixels(width: nil, height: nil, src_x: 0, src_y: 0, row_bytes: nil, image_info: nil, color_type: :rgba_8888,
                alpha_type: :premul, color_space: nil, caching_hint: :allow)
  info = image_info || ImageInfo.new(
    width: width || (self.width - src_x),
    height: height || (self.height - src_y),
    color_type: color_type,
    alpha_type: alpha_type,
    color_space: color_space
  )

  row_bytes ||= info.min_row_bytes
  byte_size = row_bytes * info.height
  pixels = FFI::MemoryPointer.new(:uint8, byte_size)

  success = Native.sk_image_read_pixels(@ptr, info.to_struct, pixels, row_bytes, src_x.to_i, src_y.to_i, caching_hint)
  raise DecodingError, 'Failed to read pixels from image' unless success

  pixels.read_bytes(byte_size)
end

#save(path, format: nil, quality: 100) ⇒ Object



178
179
180
181
182
183
# File 'lib/skia/image.rb', line 178

def save(path, format: nil, quality: 100)
  format ||= detect_format_from_path(path)
  data = encode(format, quality)
  File.binwrite(path, data.to_s)
  self
end

#save_jpeg(path, quality = 80) ⇒ Object



189
190
191
# File 'lib/skia/image.rb', line 189

def save_jpeg(path, quality = 80)
  save(path, format: :jpeg, quality: quality)
end

#save_png(path, quality = 100) ⇒ Object



185
186
187
# File 'lib/skia/image.rb', line 185

def save_png(path, quality = 100)
  save(path, format: :png, quality: quality)
end

#save_webp(path, quality = 80) ⇒ Object



193
194
195
# File 'lib/skia/image.rb', line 193

def save_webp(path, quality = 80)
  save(path, format: :webp, quality: quality)
end

#subset(rect) ⇒ Object



81
82
83
84
85
86
87
# File 'lib/skia/image.rb', line 81

def subset(rect)
  rect_struct = rect.to_struct
  ptr = Native.sk_image_make_subset_raster(@ptr, rect_struct)
  return nil if ptr.nil? || ptr.null?

  self.class.new(ptr)
end

#unique_idObject



42
43
44
# File 'lib/skia/image.rb', line 42

def unique_id
  Native.sk_image_get_unique_id(@ptr)
end

#widthObject



34
35
36
# File 'lib/skia/image.rb', line 34

def width
  Native.sk_image_get_width(@ptr)
end