Class: GD2::Image

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/gd2/image.rb

Overview

Introduction

Image is the abstract base class for Image::IndexedColor and Image::TrueColor.

Creating and Importing

Image objects are created either as a blank array of pixels:

image = Image::IndexedColor.new(width, height)
image = Image::TrueColor.new(width, height)

or by loading image data from a file or a string containing one of the supported image formats:

image = Image.load(file)
image = Image.load(string)

or by importing image data from a file given by its pathname:

image = Image.import(filename)

Exporting

After manipulating an image, it can be exported to a string in one of the supported image formats:

image.jpeg(quality = nil)
image.png(level = nil)
image.gif
image.wbmp(fgcolor)
image.gd
image.gd2(fmt = FMT_COMPRESSED)

or to a file in a format determined by the filename extension:

image.export(filename, options = {})

Direct Known Subclasses

IndexedColor, TrueColor

Defined Under Namespace

Classes: IndexedColor, TrueColor, UnrecognizedImageTypeError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#image_ptrObject (readonly)

:nodoc:



48
49
50
# File 'lib/gd2/image.rb', line 48

def image_ptr
  @image_ptr
end

#paletteObject (readonly)

The Palette object for this image



51
52
53
# File 'lib/gd2/image.rb', line 51

def palette
  @palette
end

Class Method Details

.create_image_ptr(sx, sy, alpha_blending = true) ⇒ Object

:nodoc:



205
206
207
208
209
# File 'lib/gd2/image.rb', line 205

def self.create_image_ptr(sx, sy, alpha_blending = true)  #:nodoc:
  ptr = FFIStruct::ImagePtr.new(::GD2::GD2FFI.send(create_image_sym, sx.to_i, sy.to_i))
  ::GD2::GD2FFI.send(:gdImageAlphaBlending, ptr, alpha_blending ? 1 : 0)
  ptr
end

.import(filename, options = {}) ⇒ Object

Import an image from a file with the given filename. The :format option or the file extension is used to determine the image type (jpeg, png, gif, wbmp, gd, gd2, xbm, or xpm). The resulting image will be either of class Image::TrueColor or Image::IndexedColor.

If the file format is gd2, it is optionally possible to extract only a part of the image. Use options :x, :y, :width, and :height to specify the part of the image to import.

Raises:

  • (Errno::ENOENT)


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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/gd2/image.rb', line 140

def self.import(filename, options = {})
  raise Errno::ENOENT.new(filename) unless File.exists?(filename)

  unless format = options.delete(:format)
    md = filename.match(/\.([^.]+)\z/)
    format = md ? md[1].downcase : nil
  end
  format = format.to_sym if format

  ptr = # TODO: implement xpm and xbm imports
  #if format == :xpm
    #raise ArgumentError, "Unexpected options #{options.inspect}" unless options.empty?
    #::GD2::GD2FFI.send(:gdImageCreateFromXpm, filename)
  #elsif format == :xbm
    #::GD2::GD2FFI.send(:gdImageCreateFromXbm, filename)
  if format == :gd2 && !options.empty?
    x, y, width, height =
      options.delete(:x) || 0, options.delete(:y) || 0,
      options.delete(:width)  || options.delete(:w),
      options.delete(:height) || options.delete(:h)
    raise ArgumentError, "Unexpected options #{options.inspect}" unless
      options.empty?
    raise ArgumentError, 'Missing required option :width' if width.nil?
    raise ArgumentError, 'Missing required option :height' if height.nil?
    # TODO:
    ptr = File.open(filename, 'rb') do |file|
      ::GD2::GD2FFI.send(:gdImageCreateFromGd2Part, file, x.to_i, y.to_i, width.to_i, height.to_i)
    end
  else
    raise ArgumentError, "Unexpected options #{options.inspect}" unless
      options.empty?
    create_sym = {
      :jpeg => :gdImageCreateFromJpegPtr,
      :jpg  => :gdImageCreateFromJpegPtr,
      :png  => :gdImageCreateFromPngPtr,
      :gif  => :gdImageCreateFromGifPtr,
      :wbmp => :gdImageCreateFromWBMPPtr,
      :gd   => :gdImageCreateFromGdPtr,
      :gd2  => :gdImageCreateFromGd2Ptr
    }[format]
    raise UnrecognizedImageTypeError,
      'Format (or file extension) is not recognized' unless create_sym

    file = File.open(filename, 'rb').read
    file = file.force_encoding("ASCII-8BIT") if file.respond_to? :force_encoding
    file_ptr = FFI::MemoryPointer.new(file.size, 1, false)
    file_ptr.put_bytes(0, file)

    ::GD2::GD2FFI.send(create_sym, file.size, file_ptr)
  end
  raise LibraryError if ptr.null?

  ptr = FFIStruct::ImagePtr.new(ptr)

  image = (image_true_color?(ptr) ?
    TrueColor : IndexedColor).allocate.init_with_image(ptr)

  block_given? ? yield(image) : image
end

.load(src) ⇒ Object

Load an image from a file or a string. The image type is detected automatically (JPEG, PNG, GIF, WBMP, or GD2). The resulting image will be either of class Image::TrueColor or Image::IndexedColor.

Raises:



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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 'lib/gd2/image.rb', line 72

def self.load(src)
  src = src.force_encoding("ASCII-8BIT") if src.respond_to? :force_encoding
  case src
  when File
    pos = src.pos
    magic = src.read(4)
    src.pos = pos

    data = if FFI::Platform.windows?
      File.open(src.path, 'rb').read[pos..-1]
    else
      data = src.read
    end

    data = data.force_encoding("ASCII-8BIT") if data.respond_to? :force_encoding
    args = [ data.length, data ]
  when String
    magic = src.slice(0, 4)
    args = [ src.length, src ]
  else
    raise TypeError, 'Unexpected argument type'
  end

  create = {
    :jpeg => :gdImageCreateFromJpegPtr,
    :png  => :gdImageCreateFromPngPtr,
    :gif  => :gdImageCreateFromGifPtr,
    :wbmp => :gdImageCreateFromWBMPPtr,
    :gd2  => :gdImageCreateFromGd2Ptr
  }

  type = data_type(magic) or
    raise UnrecognizedImageTypeError, 'Image data format is not recognized'
  ptr = ::GD2::GD2FFI.send(create[type], *args)
  raise LibraryError if ptr.null?

  ptr = FFIStruct::ImagePtr.new(ptr)

  image = (image_true_color?(ptr) ?
    TrueColor : IndexedColor).allocate.init_with_image(ptr)

  block_given? ? yield(image) : image
end

.new(w, h) ⇒ Object Also known as: []

Create a new image of the specified dimensions. The default image class is Image::TrueColor; call this method on Image::IndexedColor instead if a palette image is desired.



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

def self.new(w, h)
  image = (self == Image) ?
    TrueColor.new(w, h) : allocate.init_with_size(w, h)

  block_given? ? yield(image) : image
end

Instance Method Details

#==(other) ⇒ Object

Compare this image with another image. Returns false if the images are not identical.



246
247
248
# File 'lib/gd2/image.rb', line 246

def ==(other)
  (compare(other) & CMP_IMAGE).zero?
end

#[](x, y) ⇒ Object

Return the color of the pixel at image location (x, y).



292
293
294
# File 'lib/gd2/image.rb', line 292

def [](x, y)
  pixel2color(get_pixel(x, y))
end

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

Set the color of the pixel at image location (x, y).



297
298
299
# File 'lib/gd2/image.rb', line 297

def []=(x, y, color)
  set_pixel(x, y, color2pixel(color))
end

#alpha_blending=(bool) ⇒ Object

Set whether colors should be alpha blended with existing colors when pixels are modified. Alpha blending is not available for IndexedColor images.



345
346
347
# File 'lib/gd2/image.rb', line 345

def alpha_blending=(bool)
  ::GD2::GD2FFI.send(:gdImageAlphaBlending, image_ptr, bool ? 1 : 0)
end

#alpha_blending?Boolean

Return true if colors will be alpha blended into the image when pixels are modified. Returns false if colors will be copied verbatim into the image without alpha blending when pixels are modified.

Returns:

  • (Boolean)


338
339
340
# File 'lib/gd2/image.rb', line 338

def alpha_blending?
  not image_ptr[:alphaBlendingFlag].zero?
end

#aspectObject

Return the aspect ratio of this image, as a floating point ratio of the width to the height.



275
276
277
# File 'lib/gd2/image.rb', line 275

def aspect
  width.to_f / height
end

#clippingObject

Return the current clipping rectangle. Use Image#with_clipping to temporarily modify the clipping rectangle.



376
377
378
379
380
381
382
383
384
# File 'lib/gd2/image.rb', line 376

def clipping
  x1 = FFI::MemoryPointer.new(:pointer)
  y1 = FFI::MemoryPointer.new(:pointer)
  x2 = FFI::MemoryPointer.new(:pointer)
  y2 = FFI::MemoryPointer.new(:pointer)

  ::GD2::GD2FFI.send(:gdImageGetClip, image_ptr, x1, y1, x2, y2)
  [ x1.read_int, y1.read_int, x2.read_int, y2.read_int ]
end

#clips?(x, y) ⇒ Boolean

Return true if the current clipping rectangle excludes the given point.

Returns:

  • (Boolean)


401
402
403
# File 'lib/gd2/image.rb', line 401

def clips?(x, y)
  ::GD2::GD2FFI.send(:gdImageBoundsSafe, image_ptr, x.to_i, y.to_i).zero?
end

#color2pixel(color) ⇒ Object

Return a pixel value for the given color object.



319
320
321
# File 'lib/gd2/image.rb', line 319

def color2pixel(color)
  color.rgba
end

#compare(other) ⇒ Object

Compare this image with another image. Returns 0 if the images are identical, otherwise a bit field indicating the differences. See the GD2::CMP_* constants for individual bit flags.



240
241
242
# File 'lib/gd2/image.rb', line 240

def compare(other)
  ::GD2::GD2FFI.send(:gdImageCompare, image_ptr, other.image_ptr)
end

#copy_from(other, dst_x, dst_y, src_x, src_y, dst_w, dst_h, src_w = nil, src_h = nil) ⇒ Object

Copy a portion of another image to this image. If src_w and src_h are specified, the indicated portion of the source image will be resized (and resampled) to fit the indicated dimensions of the destination.

Raises:

  • (ArgumentError)


541
542
543
544
545
546
547
548
549
550
551
552
# File 'lib/gd2/image.rb', line 541

def copy_from(other, dst_x, dst_y, src_x, src_y,
    dst_w, dst_h, src_w = nil, src_h = nil)
  raise ArgumentError unless src_w.nil? == src_h.nil?
  if src_w
    ::GD2::GD2FFI.send(:gdImageCopyResampled, image_ptr, other.image_ptr,
      dst_x.to_i, dst_y.to_i, src_x.to_i, src_y.to_i, dst_w.to_i, dst_h.to_i, src_w.to_i, src_h.to_i)
  else
    ::GD2::GD2FFI.send(:gdImageCopy, image_ptr, other.image_ptr,
      dst_x.to_i, dst_y.to_i, src_x.to_i, src_y.to_i, dst_w.to_i, dst_h.to_i)
  end
  self
end

#copy_from_rotated(other, dst_x, dst_y, src_x, src_y, w, h, angle) ⇒ Object

Copy a portion of another image to this image, rotating the source portion first by the indicated angle (in radians). The dst_x and dst_y arguments indicate the center of the desired destination, and may be floating point.



558
559
560
561
562
# File 'lib/gd2/image.rb', line 558

def copy_from_rotated(other, dst_x, dst_y, src_x, src_y, w, h, angle)
  ::GD2::GD2FFI.send(:gdImageCopyRotated, image_ptr, other.image_ptr,
    dst_x.to_f, dst_y.to_f, src_x.to_i, src_y.to_i, w.to_i, h.to_i, angle.to_degrees.round.to_i)
  self
end

#crop(x, y, w, h) ⇒ Object

Like Image#crop! except a new image is returned.



597
598
599
# File 'lib/gd2/image.rb', line 597

def crop(x, y, w, h)
  clone.crop!(x, y, w, h)
end

#crop!(x, y, w, h) ⇒ Object

Crop this image to the specified dimensions, such that (x, y) becomes (0, 0).



590
591
592
593
594
# File 'lib/gd2/image.rb', line 590

def crop!(x, y, w, h)
  ptr = self.class.create_image_ptr(w, h, alpha_blending?)
  ::GD2::GD2FFI.send(:gdImageCopy, ptr, image_ptr, 0, 0, x.to_i, y.to_i, w.to_i, h.to_i)
  init_with_image(ptr)
end

#draw {|Canvas.new(self)| ... } ⇒ Object

Provide a drawing environment for a block. See GD2::Canvas.

Yields:



406
407
408
409
# File 'lib/gd2/image.rb', line 406

def draw  #:yields: canvas
  yield Canvas.new(self)
  self
end

#dupObject

Duplicate this image, copying all pixels to a new image. Contrast with Image#clone which produces a shallow copy and shares internal pixel data.



233
234
235
# File 'lib/gd2/image.rb', line 233

def dup
  self.class.superclass.load(gd2(FMT_RAW))
end

#eachObject

Iterate over each row of pixels in the image, returning an array of pixel values.



303
304
305
306
307
308
309
310
311
# File 'lib/gd2/image.rb', line 303

def each
  (0...height).each do |y|
    row = (0...width).inject(Array.new(width)) do |r, x|
      r[x] = get_pixel(x, y)
      r
    end
    yield row
  end
end

#export(filename, options = {}) ⇒ Object

Export this image to a file with the given filename. The image format is determined by the :format option, or by the file extension (jpeg, png, gif, wbmp, gd, or gd2). Returns the size of the written image data. Additional options are as arguments for the Image#jpeg, Image#png, Image#wbmp, or Image#gd2 methods.

Raises:

  • (ArgumentError)


423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
# File 'lib/gd2/image.rb', line 423

def export(filename, options = {})
  unless format = options.delete(:format)
    md = filename.match(/\.([^.]+)\z/)
    format = md ? md[1].downcase : nil
  end
  format = format.to_sym if format

  size = FFI::MemoryPointer.new(:pointer)

  case format
  when :jpeg, :jpg
    write_sym = :gdImageJpegPtr
    args = [ size, options.delete(:quality) || -1 ]
  when :png
    write_sym = :gdImagePngPtrEx
    args = [ size, options.delete(:level) || -1 ]
  when :gif
    write_sym = :gdImageGifPtr
    args = [ size ]
  when :wbmp
    write_sym = :gdImageWBMPPtr
    fgcolor = options.delete(:fgcolor)
    raise ArgumentError, 'Missing required option :fgcolor' if fgcolor.nil?
    args = [size, color2pixel(fgcolor)]
  when :gd
    write_sym = :gdImageGdPtr
    args = [ size ]
  when :gd2
    write_sym = :gdImageGd2Ptr
    args = [ options.delete(:chunk_size) || 0, options.delete(:fmt) || FMT_COMPRESSED, size ]
  else
    raise UnrecognizedImageTypeError,
      'Format (or file extension) is not recognized'
  end

  raise ArgumentError, "Unrecognized options #{options.inspect}" unless
    options.empty?

  File.open(filename, 'wb') do |file|
    begin
      img = ::GD2::GD2FFI.send(write_sym, image_ptr, *args)
      file.write(img.get_bytes(0, size.get_int(0)))
    ensure
      ::GD2::GD2FFI.gdFree(img)
    end
  end
end

#gdObject

Encode and return data for this image in ???.gd??? format. This is an internal format used by the gd library to quickly read and write images.



519
520
521
522
523
524
525
# File 'lib/gd2/image.rb', line 519

def gd
  size = FFI::MemoryPointer.new(:pointer)
  ptr = ::GD2::GD2FFI.send(:gdImageGdPtr, image_ptr, size)
  ptr.get_bytes(0, size.get_int(0))
ensure
  ::GD2::GD2FFI.send(:gdFree, ptr)
end

#gd2(fmt = FMT_COMPRESSED, chunk_size = 0) ⇒ Object

Encode and return data for this image in ???.gd2??? format. This is an internal format used by the gd library to quickly read and write images. The specified fmt may be either GD2::FMT_RAW or GD2::FMT_COMPRESSED.



530
531
532
533
534
535
536
# File 'lib/gd2/image.rb', line 530

def gd2(fmt = FMT_COMPRESSED, chunk_size = 0)
  size = FFI::MemoryPointer.new(:pointer)
  ptr = ::GD2::GD2FFI.send(:gdImageGd2Ptr, image_ptr, chunk_size.to_i, fmt.to_i, size)
  ptr.get_bytes(0, size.get_int(0))
ensure
  ::GD2::GD2FFI.send(:gdFree, ptr)
end

#get_pixel(x, y) ⇒ Object Also known as: pixel

Return the pixel value at image location (x, y).



280
281
282
# File 'lib/gd2/image.rb', line 280

def get_pixel(x, y)
  ::GD2::GD2FFI.send(:gdImageGetPixel, @image_ptr, x.to_i, y.to_i)
end

#gifObject

Encode and return data for this image in GIF format. Note that GIF only supports palette images; TrueColor images will be automatically converted to IndexedColor internally in order to create the GIF. Use Image#to_indexed_color to control this conversion more precisely.



497
498
499
500
501
502
503
# File 'lib/gd2/image.rb', line 497

def gif
  size = FFI::MemoryPointer.new(:pointer)
  ptr = ::GD2::GD2FFI.send(:gdImageGifPtr, image_ptr, size)
  ptr.get_bytes(0, size.get_int(0))
ensure
  ::GD2::GD2FFI.send(:gdFree, ptr)
end

#heightObject Also known as: h

Return the height of this image, in pixels.



263
264
265
# File 'lib/gd2/image.rb', line 263

def height
  image_ptr[:sy]
end

#init_with_image(ptr) ⇒ Object

:nodoc:



215
216
217
218
219
220
221
222
223
224
225
# File 'lib/gd2/image.rb', line 215

def init_with_image(ptr)  #:nodoc:
  @image_ptr = if ptr.is_a?(FFIStruct::ImagePtr)
    ptr
  else
    FFIStruct::ImagePtr.new(ptr)
  end

  @palette = self.class.palette_class.new(self) unless
    defined?(@palette) && @palette.image == self
  self
end

#init_with_size(sx, sy) ⇒ Object

:nodoc:



211
212
213
# File 'lib/gd2/image.rb', line 211

def init_with_size(sx, sy)  #:nodoc:
  init_with_image self.class.create_image_ptr(sx, sy)
end

#inspectObject

:nodoc:



227
228
229
# File 'lib/gd2/image.rb', line 227

def inspect   #:nodoc:
  "#<#{self.class} #{size.inspect}>"
end

#interlaced=(bool) ⇒ Object

Set whether this image will be stored in interlaced form when output as PNG or JPEG.



331
332
333
# File 'lib/gd2/image.rb', line 331

def interlaced=(bool)
  ::GD2::GD2FFI.send(:gdImageInterlace, image_ptr, bool ? 1 : 0)
end

#interlaced?Boolean

Return true if this image will be stored in interlaced form when output as PNG or JPEG.

Returns:

  • (Boolean)


325
326
327
# File 'lib/gd2/image.rb', line 325

def interlaced?
  not image_ptr[:interlace].zero?
end

#jpeg(quality = nil) ⇒ Object

Encode and return data for this image in JPEG format. The quality argument should be in the range 0???95, with higher quality values usually implying both higher quality and larger sizes.



474
475
476
477
478
479
480
# File 'lib/gd2/image.rb', line 474

def jpeg(quality = nil)
  size = FFI::MemoryPointer.new(:pointer)
  ptr = ::GD2::GD2FFI.send(:gdImageJpegPtr, image_ptr, size, quality || -1)
  ptr.get_bytes(0, size.get_int(0))
ensure
  ::GD2::GD2FFI.send(:gdFree, ptr)
end

#merge_from(other, dst_x, dst_y, src_x, src_y, w, h, pct) ⇒ Object

Merge a portion of another image into this one by the amount specified as pct (a percentage). A percentage of 1.0 is identical to Image#copy_from; a percentage of 0.0 is a no-op. Note that alpha channel information from the source image is ignored.



568
569
570
571
572
# File 'lib/gd2/image.rb', line 568

def merge_from(other, dst_x, dst_y, src_x, src_y, w, h, pct)
  ::GD2::GD2FFI.send(:gdImageCopyMerge, image_ptr, other.image_ptr,
    dst_x.to_i, dst_y.to_i, src_x.to_i, src_y.to_i, w.to_i, h.to_i, pct.to_percent.round.to_i)
  self
end

#optimize_paletteObject

Consolidate duplicate colors in this image, and eliminate all unused palette entries. This only has an effect on IndexedColor images, and is rather expensive. Returns the number of palette entries deallocated.



414
415
416
# File 'lib/gd2/image.rb', line 414

def optimize_palette
  # implemented by subclass
end

#pixel2color(pixel) ⇒ Object

Return a Color object for the given pixel value.



314
315
316
# File 'lib/gd2/image.rb', line 314

def pixel2color(pixel)
  Color.new_from_rgba(pixel)
end

#png(level = nil) ⇒ Object

Encode and return data for this image in PNG format. The level argument should be in the range 0???9 indicating the level of lossless compression (0 = none, 1 = minimal but fast, 9 = best but slow).



485
486
487
488
489
490
491
# File 'lib/gd2/image.rb', line 485

def png(level = nil)
  size = FFI::MemoryPointer.new(:pointer)
  ptr = ::GD2::GD2FFI.send(:gdImagePngPtrEx, image_ptr, size, level.to_i || -1)
  ptr.get_bytes(0, size.get_int(0))
ensure
  ::GD2::GD2FFI.send(:gdFree, ptr)
end

#polar_transform(radius) ⇒ Object

Like Image#polar_transform! except a new image is returned.



645
646
647
# File 'lib/gd2/image.rb', line 645

def polar_transform(radius)
  clone.polar_transform!(radius)
end

#polar_transform!(radius) ⇒ Object

Transform this image into a new image of width and height radius??????2, in which the X axis of the original has been remapped to ?? (angle) and the Y axis of the original has been remapped to ?? (distance from center). Note that the original image must be square.

Raises:



637
638
639
640
641
642
# File 'lib/gd2/image.rb', line 637

def polar_transform!(radius)
  raise 'Image must be square' unless width == height
  ptr = ::GD2::GD2FFI.send(:gdImageSquareToCircle, image_ptr, radius.to_i)
  raise LibraryError if ptr.null?
  init_with_image(ptr)
end

#resize(w, h, resample = true) ⇒ Object

Like Image#resize! except a new image is returned.



629
630
631
# File 'lib/gd2/image.rb', line 629

def resize(w, h, resample = true)
  clone.resize!(w, h, resample)
end

#resize!(w, h, resample = true) ⇒ Object

Resize this image to the given dimensions. If resample is true, the image pixels will be resampled; otherwise they will be stretched or shrunk as necessary without resampling.



618
619
620
621
622
623
624
625
626
# File 'lib/gd2/image.rb', line 618

def resize!(w, h, resample = true)
  ptr = self.class.create_image_ptr(w, h, false)
  ::GD2::GD2FFI.send(resample ? :gdImageCopyResampled : :gdImageCopyResized,
    ptr, image_ptr, 0, 0, 0, 0, w.to_i, h.to_i, width.to_i, height.to_i)
  alpha_blending = alpha_blending?
  init_with_image(ptr)
  self.alpha_blending = alpha_blending
  self
end

#rotate(angle, axis_x = width / 2.0, axis_y = height / 2.0) ⇒ Object

Like Image#rotate! except a new image is returned.



584
585
586
# File 'lib/gd2/image.rb', line 584

def rotate(angle, axis_x = width / 2.0, axis_y = height / 2.0)
  clone.rotate!(angle, axis_x, axis_y)
end

#rotate!(angle, axis_x = width / 2.0, axis_y = height / 2.0) ⇒ Object

Rotate this image by the given angle (in radians) about the given axis coordinates. Note that some of the edges of the image may be lost.



576
577
578
579
580
581
# File 'lib/gd2/image.rb', line 576

def rotate!(angle, axis_x = width / 2.0, axis_y = height / 2.0)
  ptr = self.class.create_image_ptr(width, height, alpha_blending?)
  ::GD2::GD2FFI.send(:gdImageCopyRotated, ptr, image_ptr,
    axis_x.to_f, axis_y.to_f, 0, 0, width.to_i, height.to_i, angle.to_degrees.round.to_i)
  init_with_image(ptr)
end

#save_alpha=(bool) ⇒ Object

Set whether this image will be stored with full alpha channel information when output as PNG.



357
358
359
# File 'lib/gd2/image.rb', line 357

def save_alpha=(bool)
  ::GD2::GD2FFI.send(:gdImageSaveAlpha, image_ptr, bool ? 1 : 0)
end

#save_alpha?Boolean

Return true if this image will be stored with full alpha channel information when output as PNG.

Returns:

  • (Boolean)


351
352
353
# File 'lib/gd2/image.rb', line 351

def save_alpha?
  not image_ptr[:saveAlphaFlag].zero?
end

#set_pixel(x, y, value) ⇒ Object

Set the pixel value at image location (x, y).



286
287
288
289
# File 'lib/gd2/image.rb', line 286

def set_pixel(x, y, value)
  ::GD2::GD2FFI.send(:gdImageSetPixel, @image_ptr, x.to_i, y.to_i, value.to_i)
  nil
end

#sharpen(pct) ⇒ Object

Sharpen this image by pct (a percentage) which can be greater than 1.0. Transparency/alpha channel are not altered. This has no effect on IndexedColor images.



652
653
654
# File 'lib/gd2/image.rb', line 652

def sharpen(pct)
  self
end

#sizeObject

Return the size of this image as an array [width, height], in pixels.



269
270
271
# File 'lib/gd2/image.rb', line 269

def size
  [width, height]
end

#to_indexed_color(colors = MAX_COLORS, dither = true) ⇒ Object

Return this image as an IndexedColor image, creating a copy if necessary. colors indicates the maximum number of palette colors to use, and dither controls whether dithering is used.

Raises:



664
665
666
667
668
669
670
671
672
673
674
675
676
677
# File 'lib/gd2/image.rb', line 664

def to_indexed_color(colors = MAX_COLORS, dither = true)
  ptr = ::GD2::GD2FFI.send(:gdImageCreatePaletteFromTrueColor,
    to_true_color.image_ptr, dither ? 1 : 0, colors.to_i)
  raise LibraryError if ptr.null?

  obj = IndexedColor.allocate.init_with_image(ptr)

  # fix for gd bug where image->open[] is not properly initialized
  (0...obj.image_ptr[:colorsTotal]).each do |i|
    obj.image_ptr[:open][i] = 0
  end

  obj
end

#to_true_colorObject

Return this image as a TrueColor image, creating a copy if necessary.



657
658
659
# File 'lib/gd2/image.rb', line 657

def to_true_color
  self
end

#transparentObject

Return the transparent color for this image, or nil if none has been set.



363
364
365
366
# File 'lib/gd2/image.rb', line 363

def transparent
  pixel = image_ptr[:transparent]
  pixel == -1 ? nil : pixel2color(pixel)
end

#transparent=(color) ⇒ Object

Set or unset the transparent color for this image.



369
370
371
372
# File 'lib/gd2/image.rb', line 369

def transparent=(color)
  ::GD2::GD2FFI.send(:gdImageColorTransparent, image_ptr,
    color.nil? ? -1 : color2pixel(color))
end

#true_color?Boolean

Return true if this image is a TrueColor image.

Returns:

  • (Boolean)


251
252
253
254
# File 'lib/gd2/image.rb', line 251

def true_color?
  kind_of?(TrueColor)
  # self.class.image_true_color?(image_ptr)
end

#uncrop(x1, y1 = x1, x2 = x1, y2 = y1) ⇒ Object

Like Image#uncrop! except a new image is returned.



611
612
613
# File 'lib/gd2/image.rb', line 611

def uncrop(x1, y1 = x1, x2 = x1, y2 = y1)
  clone.uncrop!(x1, y1, x2, y2)
end

#uncrop!(x1, y1 = x1, x2 = x1, y2 = y1) ⇒ Object

Expand the left, top, right, and bottom borders of this image by the given number of pixels.



603
604
605
606
607
608
# File 'lib/gd2/image.rb', line 603

def uncrop!(x1, y1 = x1, x2 = x1, y2 = y1)
  ptr = self.class.create_image_ptr(x1 + width + x2, y1 + height + y2,
    alpha_blending?)
  ::GD2::GD2FFI.send(:gdImageCopy, ptr, image_ptr, x1.to_i, y1.to_i, 0, 0, width.to_i, height.to_i)
  init_with_image(ptr)
end

#wbmp(fgcolor) ⇒ Object

Encode and return data for this image in WBMP format. WBMP currently supports only black and white images; the specified fgcolor will be used as the foreground color (black), and all other colors will be considered ???background??? (white).



509
510
511
512
513
514
515
# File 'lib/gd2/image.rb', line 509

def wbmp(fgcolor)
  size = FFI::MemoryPointer.new(:pointer)
  ptr = ::GD2::GD2FFI.send(:gdImageWBMPPtr, image_ptr, size, color2pixel(fgcolor))
  ptr.get_bytes(0, size.get_int(0))
ensure
  ::GD2::GD2FFI.send(:gdFree, ptr)
end

#widthObject Also known as: w

Return the width of this image, in pixels.



257
258
259
# File 'lib/gd2/image.rb', line 257

def width
  image_ptr[:sx]
end

#with_clipping(x1, y1, x2, y2) ⇒ Object

Temporarily set the clipping rectangle during the execution of a block. Pixels outside this rectangle will not be modified by drawing or copying operations.



389
390
391
392
393
394
395
396
397
398
# File 'lib/gd2/image.rb', line 389

def with_clipping(x1, y1, x2, y2)   #:yields: image
  clip = clipping
  begin
    ::GD2::GD2FFI.send(:gdImageSetClip, image_ptr, x1.to_i, y1.to_i, x2.to_i, y2.to_i)
    yield self
    self
  ensure
    ::GD2::GD2FFI.send(:gdImageSetClip, image_ptr, *clip)
  end
end