Class: DXOpal::Image
- Inherits:
-
RemoteResource
- Object
- RemoteResource
- DXOpal::Image
- Defined in:
- lib/dxopal/image.rb
Overview
Represents an image Each instance of Image has its own off-screen canvas.
Constant Summary collapse
- BLEND_TYPES =
{ alpha: "source-over", # A over B (Default) add: "lighter" # A + B }
Instance Attribute Summary collapse
-
#canvas ⇒ Object
readonly
Returns the value of attribute canvas.
-
#ctx ⇒ Object
readonly
Returns the value of attribute ctx.
-
#height ⇒ Object
readonly
Returns the value of attribute height.
-
#loaded ⇒ Object
Returns the value of attribute loaded.
-
#promise ⇒ Object
Returns the value of attribute promise.
-
#width ⇒ Object
readonly
Returns the value of attribute width.
Class Method Summary collapse
-
._load(path_or_url) ⇒ Object
Load remote image (called via Window.load_resources).
-
.hsl2rgb(h, s, l) ⇒ Object
Convert HSL to RGB (DXOpal original; not in DXRuby) h: 0-359 s: 0-100 l: 0-100.
- .load(path_or_url) ⇒ Object
Instance Method Summary collapse
-
#[](x, y) ⇒ Object
Get a pixel as ARGB array.
-
#[]=(x, y, color) ⇒ Object
Put a pixel on this image.
-
#_draw_raw_image(x, y, raw_img) ⇒ Object
Copy an <img> onto this image.
-
#_image_data(x = 0, y = 0, w = @width, h = @height) ⇒ Object
Return .getImageData.
-
#_put_image_data(image_data, x = 0, y = 0) ⇒ Object
Call .putImageData.
-
#_resize(w, h) ⇒ Object
Set size of this image.
-
#_rgb(color) ⇒ Object
Return a string like 'rgb(255, 255, 255)' `color` is 3 or 4 numbers.
-
#_rgba(color) ⇒ Object
Return a string like 'rgba(255, 255, 255, 128)' `color` is 3 or 4 numbers.
-
#_rgba_ary(color) ⇒ Object
Return an array like `[255, 255, 255, 128]`.
-
#box(x1, y1, x2, y2, color) ⇒ Object
Draw a rectangle on this image.
-
#box_fill(x1, y1, x2, y2, color) ⇒ Object
Draw a filled box on this image.
-
#circle(x, y, r, color) ⇒ Object
Draw a circle on this image.
-
#circle_fill(x, y, r, color) ⇒ Object
Draw a filled circle on this image.
-
#clear ⇒ Object
Clear this image (i.e. fill with `[0,0,0,0]`).
-
#compare(x, y, color) ⇒ Object
Return true if the pixel at `(x, y)` has the `color`.
-
#draw(x, y, image) ⇒ Object
Draw an Image on this image.
- #draw_ex(x, y, image, options = {}) ⇒ Object
-
#draw_font(x, y, string, font, color = [255,255,255]) ⇒ Object
Draw some text on this image.
-
#draw_rot(x, y, image, angle, center_x = nil, center_y = nil) ⇒ Object
Draw an Image on this image with rotation - angle: Rotation angle (radian) - center_x, center_y: Rotation center in the `image` (default: center of the `image`).
-
#draw_scale(x, y, image, scale_x, scale_y, center_x = nil, center_y = nil) ⇒ Object
Draw an Image on this image with scaling - scale_x, scale_y: scaling factor (eg. 1.5) - center_x, center_y: scaling center (in other words, the point which does not move by this scaling. Default: image center).
-
#fill(color) ⇒ Object
Fill this image with `color`.
-
#initialize(width, height, color = C_DEFAULT, canvas: nil) ⇒ Image
constructor
Create an instance of Image.
-
#line(x1, y1, x2, y2, color) ⇒ Object
Draw a line on this image.
- #load(path_or_url) ⇒ Object
- #loaded? ⇒ Boolean
- #onload(&block) ⇒ Object
-
#set_color_key(color) ⇒ Object
Set alpha of the pixels of the given color to 0 - color : RGB color (If ARGV color is given, A is just ignored).
-
#slice(x, y, width, height) ⇒ Object
Return an Image which is a copy of the specified area.
-
#slice_tiles(xcount, ycount) ⇒ Object
Slice this image into xcount*ycount tiles.
-
#triangle(x1, y1, x2, y2, x3, y3, color) ⇒ Object
Draw a triangle on this image.
-
#triangle_fill(x1, y1, x2, y2, x3, y3, color) ⇒ Object
Draw a filled triangle on this image.
Methods inherited from RemoteResource
[], _klass_name, _load_resources, add_class, register
Constructor Details
#initialize(width, height, color = C_DEFAULT, canvas: nil) ⇒ Image
Create an instance of Image
91 92 93 94 95 96 97 |
# File 'lib/dxopal/image.rb', line 91 def initialize(width, height, color=C_DEFAULT, canvas: nil) @width, @height = width, height @canvas = canvas || `document.createElement("canvas")` @ctx = `#{@canvas}.getContext('2d')` _resize(@width, @height) box_fill(0, 0, @width, @height, color) end |
Instance Attribute Details
#canvas ⇒ Object (readonly)
Returns the value of attribute canvas.
98 99 100 |
# File 'lib/dxopal/image.rb', line 98 def canvas @canvas end |
#ctx ⇒ Object (readonly)
Returns the value of attribute ctx.
98 99 100 |
# File 'lib/dxopal/image.rb', line 98 def ctx @ctx end |
#height ⇒ Object (readonly)
Returns the value of attribute height.
98 99 100 |
# File 'lib/dxopal/image.rb', line 98 def height @height end |
#loaded ⇒ Object
Returns the value of attribute loaded.
59 60 61 |
# File 'lib/dxopal/image.rb', line 59 def loaded @loaded end |
#promise ⇒ Object
Returns the value of attribute promise.
59 60 61 |
# File 'lib/dxopal/image.rb', line 59 def promise @promise end |
#width ⇒ Object (readonly)
Returns the value of attribute width.
98 99 100 |
# File 'lib/dxopal/image.rb', line 98 def width @width end |
Class Method Details
._load(path_or_url) ⇒ Object
Load remote image (called via Window.load_resources)
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/dxopal/image.rb', line 38 def self._load(path_or_url) raw_img = `new Image()` img_promise = %x{ new Promise(function(resolve, reject) { raw_img.onload = function() { resolve(raw_img); }; raw_img.src = path_or_url; }); } img = new(0, 0) %x{ #{img_promise}.then(function(raw_img){ img.$_resize(raw_img.width, raw_img.height); img.$_draw_raw_image(0, 0, raw_img); }); } return img, img_promise end |
.hsl2rgb(h, s, l) ⇒ Object
Convert HSL to RGB (DXOpal original; not in DXRuby) h: 0-359 s: 0-100 l: 0-100
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/dxopal/image.rb', line 13 def self.hsl2rgb(h, s, l) if l < 50 max = 2.55 * (l + l*(s/100.0)) min = 2.55 * (l - l*(s/100.0)) else max = 2.55 * (l + (100-l)*(s/100.0)) min = 2.55 * (l - (100-l)*(s/100.0)) end case h when 0...60 [max, (h/60.0)*(max-min) + min, min] when 60...120 [((120-h)/60.0)*(max-min) + min, max, min] when 120...180 [min, max, ((h-120)/60.0)*(max-min) + min] when 180...240 [min, ((240-h)/60.0)*(max-min) + min, max] when 240...300 [((h-240)/60.0)*(max-min) + min, min, max] else [max, min, ((360-h)/60.0)*(max-min) + min] end end |
.load(path_or_url) ⇒ Object
62 63 64 |
# File 'lib/dxopal/image.rb', line 62 def self.load(path_or_url) return new(1, 1).load(path_or_url) end |
Instance Method Details
#[](x, y) ⇒ Object
Get a pixel as ARGB array
175 176 177 178 179 180 181 182 183 184 |
# File 'lib/dxopal/image.rb', line 175 def [](x, y) ctx = @ctx ret = nil %x{ var pixel = ctx.getImageData(x, y, 1, 1); var rgba = pixel.data; ret = [rgba[3], rgba[0], rgba[1], rgba[2]]; } return ret end |
#[]=(x, y, color) ⇒ Object
Put a pixel on this image
187 188 189 |
# File 'lib/dxopal/image.rb', line 187 def []=(x, y, color) box_fill(x, y, x+1, y+1, color) end |
#_draw_raw_image(x, y, raw_img) ⇒ Object
Copy an <img> onto this image
345 346 347 348 349 |
# File 'lib/dxopal/image.rb', line 345 def _draw_raw_image(x, y, raw_img) %x{ #{@ctx}.drawImage(#{raw_img}, x, y); } end |
#_image_data(x = 0, y = 0, w = @width, h = @height) ⇒ Object
Return .getImageData
352 353 354 |
# File 'lib/dxopal/image.rb', line 352 def _image_data(x=0, y=0, w=@width, h=@height) return `#{@ctx}.getImageData(x, y, w, h)` end |
#_put_image_data(image_data, x = 0, y = 0) ⇒ Object
Call .putImageData
357 358 359 |
# File 'lib/dxopal/image.rb', line 357 def _put_image_data(image_data, x=0, y=0) `#{@ctx}.putImageData(image_data, x, y)` end |
#_resize(w, h) ⇒ Object
Set size of this image
101 102 103 104 105 106 107 |
# File 'lib/dxopal/image.rb', line 101 def _resize(w, h) @width, @height = w, h %x{ #{@canvas}.width = w; #{@canvas}.height = h; } end |
#_rgb(color) ⇒ Object
Return a string like 'rgb(255, 255, 255)' `color` is 3 or 4 numbers
363 364 365 366 367 368 369 370 371 372 373 374 |
# File 'lib/dxopal/image.rb', line 363 def _rgb(color) case color.length when 4 # Just ignore alpha rgb = color[1, 3] when 3 rgb = color else raise "invalid color: #{color.inspect}" end return "rgb(" + rgb.join(', ') + ")"; end |
#_rgba(color) ⇒ Object
Return a string like 'rgba(255, 255, 255, 128)' `color` is 3 or 4 numbers
378 379 380 |
# File 'lib/dxopal/image.rb', line 378 def _rgba(color) return "rgba(" + _rgba_ary(color).join(', ') + ")" end |
#_rgba_ary(color) ⇒ Object
Return an array like `[255, 255, 255, 128]`
383 384 385 386 387 388 389 390 391 392 393 394 |
# File 'lib/dxopal/image.rb', line 383 def _rgba_ary(color) case color.length when 4 # color is ARGB in DXRuby, so move A to the last color[1, 3] + [color[0]/255.0] when 3 # Complement 255 as alpha color + [1.0] else raise "invalid color: #{color.inspect}" end end |
#box(x1, y1, x2, y2, color) ⇒ Object
Draw a rectangle on this image
223 224 225 226 227 228 229 230 231 232 |
# File 'lib/dxopal/image.rb', line 223 def box(x1, y1, x2, y2, color) ctx = @ctx %x{ ctx.beginPath(); ctx.strokeStyle = #{_rgba(color)}; ctx.rect(x1+0.5, y1+0.5, x2-x1, y2-y1); ctx.stroke(); } return self end |
#box_fill(x1, y1, x2, y2, color) ⇒ Object
Draw a filled box on this image
235 236 237 238 239 240 241 242 243 |
# File 'lib/dxopal/image.rb', line 235 def box_fill(x1, y1, x2, y2, color) ctx = @ctx %x{ ctx.beginPath(); ctx.fillStyle = #{_rgba(color)}; ctx.fillRect(x1, y1, x2-x1, y2-y1); } return self end |
#circle(x, y, r, color) ⇒ Object
Draw a circle on this image
246 247 248 249 250 251 252 253 254 255 |
# File 'lib/dxopal/image.rb', line 246 def circle(x, y, r, color) ctx = @ctx %x{ ctx.beginPath(); ctx.strokeStyle = #{_rgba(color)}; ctx.arc(x+0.5, y+0.5, r, 0, Math.PI*2, false) ctx.stroke(); } return self end |
#circle_fill(x, y, r, color) ⇒ Object
Draw a filled circle on this image
258 259 260 261 262 263 264 265 266 267 |
# File 'lib/dxopal/image.rb', line 258 def circle_fill(x, y, r, color) ctx = @ctx %x{ ctx.beginPath(); ctx.fillStyle = #{_rgba(color)}; ctx.arc(x, y, r, 0, Math.PI*2, false) ctx.fill(); } return self end |
#clear ⇒ Object
Clear this image (i.e. fill with `[0,0,0,0]`)
304 305 306 |
# File 'lib/dxopal/image.rb', line 304 def clear fill([0, 0, 0, 0]) end |
#compare(x, y, color) ⇒ Object
Return true if the pixel at `(x, y)` has the `color`
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/dxopal/image.rb', line 192 def compare(x, y, color) ctx = @ctx rgba1 = _rgba_ary(color) rgba2 = nil ret = nil %x{ var pixel = ctx.getImageData(x, y, 1, 1); rgba2 = pixel.data; // TODO: what is the right way to compare an Array and an Uint8ClampedArray? ret = rgba1[0] == rgba2[0] && rgba1[1] == rgba2[1] && rgba1[2] == rgba2[2] && rgba1[3] == rgba2[3] } return ret end |
#draw(x, y, image) ⇒ Object
Draw an Image on this image
110 111 112 113 114 115 |
# File 'lib/dxopal/image.rb', line 110 def draw(x, y, image) %x{ #{@ctx}.drawImage(#{image.canvas}, x, y); } return self end |
#draw_ex(x, y, image, options = {}) ⇒ Object
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/dxopal/image.rb', line 137 def draw_ex(x, y, image, ={}) scale_x = [:scale_x] || 1 scale_y = [:scale_y] || 1 center_x = [:center_x] || image.width/2 center_y = [:center_y] || image.height/2 alpha = [:alpha] || 255 blend = [:blend] || :alpha angle = [:angle] || 0 cx = x + center_x cy = y + center_y %x{ #{@ctx}.translate(cx, cy); #{@ctx}.rotate(angle * Math.PI / 180.0); #{@ctx}.scale(scale_x, scale_y); #{@ctx}.save(); #{@ctx}.globalAlpha = alpha / 255; #{@ctx}.globalCompositeOperation = #{BLEND_TYPES[blend]}; #{@ctx}.drawImage(#{image.canvas}, x-cx, y-cy); #{@ctx}.restore(); #{@ctx}.setTransform(1, 0, 0, 1, 0, 0); // reset } return self end |
#draw_font(x, y, string, font, color = [255,255,255]) ⇒ Object
Draw some text on this image
163 164 165 166 167 168 169 170 171 172 |
# File 'lib/dxopal/image.rb', line 163 def draw_font(x, y, string, font, color=[255,255,255]) ctx = @ctx %x{ ctx.font = #{font._spec_str}; ctx.textBaseline = 'top'; ctx.fillStyle = #{_rgba(color)}; ctx.fillText(string, x, y); } return self end |
#draw_rot(x, y, image, angle, center_x = nil, center_y = nil) ⇒ Object
Draw an Image on this image with rotation
-
angle: Rotation angle (radian)
-
center_x, center_y: Rotation center in the `image` (default: center of the `image`)
128 129 130 |
# File 'lib/dxopal/image.rb', line 128 def draw_rot(x, y, image, angle, center_x=nil, center_y=nil) draw_ex(x, y, image, angle: angle, center_x: center_x, center_y: center_y) end |
#draw_scale(x, y, image, scale_x, scale_y, center_x = nil, center_y = nil) ⇒ Object
Draw an Image on this image with scaling
-
scale_x, scale_y: scaling factor (eg. 1.5)
-
center_x, center_y: scaling center (in other words, the point which does not move by this scaling. Default: image center)
121 122 123 |
# File 'lib/dxopal/image.rb', line 121 def draw_scale(x, y, image, scale_x, scale_y, center_x=nil, center_y=nil) draw_ex(x, y, image, scale_x: scale_x, scale_y: scale_y, center_x: center_x, center_y: center_y) end |
#fill(color) ⇒ Object
Fill this image with `color`
299 300 301 |
# File 'lib/dxopal/image.rb', line 299 def fill(color) box_fill(0, 0, @width-1, @height-1, color) end |
#line(x1, y1, x2, y2, color) ⇒ Object
Draw a line on this image
210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/dxopal/image.rb', line 210 def line(x1, y1, x2, y2, color) ctx = @ctx %x{ ctx.beginPath(); ctx.strokeStyle = #{_rgba(color)}; ctx.moveTo(x1+0.5, y1+0.5); ctx.lineTo(x2+0.5, y2+0.5); ctx.stroke(); } return self end |
#load(path_or_url) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/dxopal/image.rb', line 66 def load(path_or_url) raw_img = `new Image()` @promise = %x{ new Promise(function(resolve, reject) { raw_img.onload = function() { self.$_resize(raw_img.width, raw_img.height); self.$_draw_raw_image(0, 0, raw_img); self.loaded = #{true}; resolve(); }; raw_img.src = path_or_url; }); } return self end |
#loaded? ⇒ Boolean
60 |
# File 'lib/dxopal/image.rb', line 60 def loaded?; loaded; end |
#onload(&block) ⇒ Object
82 83 84 85 86 87 88 |
# File 'lib/dxopal/image.rb', line 82 def onload(&block) %x{ #{@promise}.then(function(response){ #{block.call()} }); } end |
#set_color_key(color) ⇒ Object
Set alpha of the pixels of the given color to 0
-
color : RGB color (If ARGV color is given, A is just ignored)
329 330 331 332 333 334 335 336 337 338 339 340 341 342 |
# File 'lib/dxopal/image.rb', line 329 def set_color_key(color) r, g, b, _ = _rgba_ary(color) data = _image_data() %x{ var buf = data.data; for(var i = 0; i < buf.length; i += 4){ if (buf[i] == r && buf[i+1] == g && buf[i+2] == b) { buf[i+3] = 0 } } } _put_image_data(data) end |
#slice(x, y, width, height) ⇒ Object
Return an Image which is a copy of the specified area
309 310 311 312 313 314 |
# File 'lib/dxopal/image.rb', line 309 def slice(x, y, width, height) newimg = Image.new(width, height) data = _image_data(x, y, width, height) newimg._put_image_data(data) return newimg end |
#slice_tiles(xcount, ycount) ⇒ Object
Slice this image into xcount*ycount tiles
317 318 319 320 321 322 323 324 325 |
# File 'lib/dxopal/image.rb', line 317 def slice_tiles(xcount, ycount) tile_w = @width / xcount tile_h = @height / ycount return (0...ycount).flat_map{|v| (0...xcount).map{|u| slice(tile_w * u, tile_h * v, tile_w, tile_h) } } end |
#triangle(x1, y1, x2, y2, x3, y3, color) ⇒ Object
Draw a triangle on this image
270 271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/dxopal/image.rb', line 270 def triangle(x1, y1, x2, y2, x3, y3, color) ctx = @ctx %x{ ctx.beginPath(); ctx.strokeStyle = #{_rgba(color)}; ctx.moveTo(x1+0.5, y1+0.5); ctx.lineTo(x2+0.5, y2+0.5); ctx.lineTo(x3+0.5, y3+0.5); ctx.lineTo(x1+0.5, y1+0.5); ctx.stroke(); } return self end |
#triangle_fill(x1, y1, x2, y2, x3, y3, color) ⇒ Object
Draw a filled triangle on this image
285 286 287 288 289 290 291 292 293 294 295 296 |
# File 'lib/dxopal/image.rb', line 285 def triangle_fill(x1, y1, x2, y2, x3, y3, color) ctx = @ctx %x{ ctx.beginPath(); ctx.fillStyle = #{_rgba(color)}; ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.lineTo(x3, y3); ctx.fill(); } return self end |