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, MemoryAllocationError, TrueColor, UnrecognizedImageTypeError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#image_ptrObject (readonly)

:nodoc:



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

def image_ptr
  @image_ptr
end

#paletteObject (readonly)

The Palette object for this image



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

def palette
  @palette
end

Class Method Details

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

:nodoc:

Raises:

  • (ArgumentError)


206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/gd2/image.rb', line 206

def self.create_image_ptr(sx, sy, alpha_blending = true)  #:nodoc:
  x = sx.to_i
  y = sy.to_i

  raise ArgumentError, "sx must be > 0" unless x.positive?
  raise ArgumentError, "sy must be > 0" unless y.positive?

  ptr = FFIStruct::ImagePtr.new(::GD2::GD2FFI.send(create_image_sym, x, y))

  raise MemoryAllocationError, "Could not allocation memory for image" if ptr.null?

  ::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)


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
199
# File 'lib/gd2/image.rb', line 141

def self.import(filename, options = {})
  raise Errno::ENOENT.new(filename) unless File.exist?(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:



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
115
# File 'lib/gd2/image.rb', line 73

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.



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

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.



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

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

#[](x, y) ⇒ Object

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



302
303
304
# File 'lib/gd2/image.rb', line 302

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

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

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



307
308
309
# File 'lib/gd2/image.rb', line 307

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.



355
356
357
# File 'lib/gd2/image.rb', line 355

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)


348
349
350
# File 'lib/gd2/image.rb', line 348

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.



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

def aspect
  width.to_f / height
end

#clippingObject

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



386
387
388
389
390
391
392
393
394
# File 'lib/gd2/image.rb', line 386

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)


411
412
413
# File 'lib/gd2/image.rb', line 411

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.



329
330
331
# File 'lib/gd2/image.rb', line 329

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.



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

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)


551
552
553
554
555
556
557
558
559
560
561
562
# File 'lib/gd2/image.rb', line 551

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.



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

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.



607
608
609
# File 'lib/gd2/image.rb', line 607

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).



600
601
602
603
604
# File 'lib/gd2/image.rb', line 600

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:



416
417
418
419
# File 'lib/gd2/image.rb', line 416

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.



243
244
245
# File 'lib/gd2/image.rb', line 243

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.



313
314
315
316
317
318
319
320
321
# File 'lib/gd2/image.rb', line 313

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)


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
470
471
472
473
474
475
476
477
478
479
# File 'lib/gd2/image.rb', line 433

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.



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

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.



540
541
542
543
544
545
546
# File 'lib/gd2/image.rb', line 540

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).



290
291
292
# File 'lib/gd2/image.rb', line 290

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.



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

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.



273
274
275
# File 'lib/gd2/image.rb', line 273

def height
  image_ptr[:sy]
end

#init_with_image(ptr) ⇒ Object

:nodoc:



225
226
227
228
229
230
231
232
233
234
235
# File 'lib/gd2/image.rb', line 225

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:



221
222
223
# File 'lib/gd2/image.rb', line 221

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

#inspectObject

:nodoc:



237
238
239
# File 'lib/gd2/image.rb', line 237

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.



341
342
343
# File 'lib/gd2/image.rb', line 341

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)


335
336
337
# File 'lib/gd2/image.rb', line 335

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.



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

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.



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

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.



424
425
426
# File 'lib/gd2/image.rb', line 424

def optimize_palette
  # implemented by subclass
end

#pixel2color(pixel) ⇒ Object

Return a Color object for the given pixel value.



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

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).



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

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.



655
656
657
# File 'lib/gd2/image.rb', line 655

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:



647
648
649
650
651
652
# File 'lib/gd2/image.rb', line 647

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.



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

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.



628
629
630
631
632
633
634
635
636
# File 'lib/gd2/image.rb', line 628

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.



594
595
596
# File 'lib/gd2/image.rb', line 594

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.



586
587
588
589
590
591
# File 'lib/gd2/image.rb', line 586

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.



367
368
369
# File 'lib/gd2/image.rb', line 367

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)


361
362
363
# File 'lib/gd2/image.rb', line 361

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

#set_pixel(x, y, value) ⇒ Object

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



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

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.



662
663
664
# File 'lib/gd2/image.rb', line 662

def sharpen(pct)
  self
end

#sizeObject

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



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

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:



674
675
676
677
678
679
680
681
682
683
684
685
686
687
# File 'lib/gd2/image.rb', line 674

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.



667
668
669
# File 'lib/gd2/image.rb', line 667

def to_true_color
  self
end

#transparentObject

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



373
374
375
376
# File 'lib/gd2/image.rb', line 373

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

#transparent=(color) ⇒ Object

Set or unset the transparent color for this image.



379
380
381
382
# File 'lib/gd2/image.rb', line 379

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)


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

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.



621
622
623
# File 'lib/gd2/image.rb', line 621

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.



613
614
615
616
617
618
# File 'lib/gd2/image.rb', line 613

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).



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

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.



267
268
269
# File 'lib/gd2/image.rb', line 267

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.



399
400
401
402
403
404
405
406
407
408
# File 'lib/gd2/image.rb', line 399

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