Class: ImageVoodoo

Inherits:
Object
  • Object
show all
Includes:
Shapes, Java
Defined in:
lib/image_voodoo.rb,
lib/image_voodoo/awt.rb,
lib/image_voodoo/gae.rb,
lib/image_voodoo/version.rb,
lib/image_voodoo/metadata.rb,
lib/image_voodoo/awt/shapes.rb,
lib/image_voodoo/needs_head.rb,
lib/image_voodoo/awt/core_ext/graphics2d.rb,
lib/image_voodoo/awt/core_ext/buffered_image.rb

Overview

Hide in ImageVoodoo so awt.rb can see this and we will not polute global

Defined Under Namespace

Modules: Shapes Classes: AdobeJpegDirectory, BmpHeaderDirectory, BufferedImage, CanonMakernoteDirectory, CasioType1MakernoteDirectory, CasioType2MakernoteDirectory, Directory, ExifIFD0Directory, ExifInteropDirectory, ExifSubIFDDirectory, ExifThumbnailDirectory, FujifilmMakernoteDirectory, GifHeaderDirectory, GpsDirectory, Graphics2D, IccDirectory, IptcDirectory, JImagePanel, JfifDirectory, JpegCommentDirectory, JpegDirectory, KyoceraMakernoteDirectory, LeicaMakernoteDirectory, Metadata, NikonType1MakernoteDirectory, NikonType2MakernoteDirectory, OlympusMakernoteDirectory, PanasonicMakernoteDirectory, PentaxMakernoteDirectory, PhotoshopDirectory, PngChromaticitiesDirectory, PngDirectory, PsdHeaderDirectory, RicohMakernoteDirectory, SanyoMakernoteDirectory, SigmaMakernoteDirectory, SonyType1MakernoteDirectory, SonyType6MakernoteDirectory, WindowClosed, XmpDirectory

Constant Summary collapse

JFile =
java.io.File
ImageService =
ImagesServiceFactory.images_service
VERSION =
'0.9.3'
DIRECTORY_MAP =
{
  'Adobe Jpeg' => AdobeJpegDirectory,
  'Bmp Header' => BmpHeaderDirectory,
  'Exif IFD0' => ExifIFD0Directory,
  'Exif Interop' => ExifInteropDirectory,
  'Exif Sub IFD' => ExifSubIFDDirectory,
  'Exif Thumbnail' => ExifThumbnailDirectory,
  'Gps' => GpsDirectory,
  'Canon Makernote' => CanonMakernoteDirectory,
  'Casio Type 1 Makernote' => CasioType1MakernoteDirectory,
  'Casio Type 2 Makernote' => CasioType2MakernoteDirectory,
  'Fujifilm Makernote' => FujifilmMakernoteDirectory,
  'Kyocera Makernote' => KyoceraMakernoteDirectory,
  'Leica Makernote' => LeicaMakernoteDirectory,
  'Nikon Type 1 Makernote' => NikonType1MakernoteDirectory,
  'Nikon Type 2 Makernote' => NikonType2MakernoteDirectory,
  'Olympus Makernote' => OlympusMakernoteDirectory,
  'Panasonic Makernote' => PanasonicMakernoteDirectory,
  'Pentax Makernote' => PentaxMakernoteDirectory,
  'Ricoh Makernote' => RicohMakernoteDirectory,
  'Sanyo Makernote' => SanyoMakernoteDirectory,
  'Sigma Makernote' => SigmaMakernoteDirectory,
  'Sony Type 1 Makernote' => SonyType1MakernoteDirectory,
  'Sony Type 6 Makernote' => SonyType6MakernoteDirectory,
  'Gif Header' => GifHeaderDirectory,
  'Icc' => IccDirectory,
  'Iptc' => IptcDirectory,
  'Jfif' => JfifDirectory,
  'Jpeg Comment' => JpegCommentDirectory,
  'Jpeg' => JpegDirectory,
  'Photoshop' => PhotoshopDirectory,
  'Psd Header' => PsdHeaderDirectory,
  'Png Chromaticities' => PngChromaticitiesDirectory,
  'Png' => PngDirectory,
  'Xmp' => XmpDirectory,

  # Aliases
  'IFD0' => ExifIFD0Directory
}.freeze
NEEDS_HEAD =
true

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Shapes

#add_border, #as_color, #border_style, #paint_border, #rect, #rect_rounded, #square, #square_rounded

Constructor Details

#initialize(io, src, format = nil) ⇒ ImageVoodoo

Returns a new instance of ImageVoodoo.



53
54
55
56
# File 'lib/image_voodoo.rb', line 53

def initialize(io, src, format=nil)
  @io, @src, @format = io, src, format
  @quality = nil # nil means no specific quality ever specified
end

Instance Attribute Details

#quality(amount) ⇒ Object

Set quality you want resulting image to be once you save or extract bytes for the image. Note: This will only work for lossy image formats like PNG of JPEG. For others it will be ignored.



153
154
155
156
157
158
159
160
161
# File 'lib/image_voodoo.rb', line 153

def quality(amount)
  if amount < 0.0 || amount > 1.0
    raise ArgumentError, 'Quality must be between 0.0 and 1.0'
  end

  target = dup
  target.quality = amount
  block_given? ? yield(target) : target
end

Class Method Details

.canvas(width, height, rgb = '000000') ⇒ Object

AWT-only Create an image of width x height filled with a single color.



113
114
115
116
# File 'lib/image_voodoo/awt.rb', line 113

def self.canvas(width, height, rgb='000000')
  image = ImageVoodoo.new(@io, BufferedImage.new(width, height, ARGB))
  image.rect(0, 0, width, height, rgb)
end

.from_url(source) ⇒ Object

TODO: Figure out how to determine whether source has alpha or not Experimental: Read an image from the url source and yield/return that image.



94
95
96
97
98
99
100
# File 'lib/image_voodoo/awt.rb', line 94

def self.from_url(source)
  image = image_from_url source
  target = paint(BufferedImage.new(image.width, image.height, RGB)) do |g|
    g.draw_image image, 0, 0, nil
  end
  block_given? ? yield(target) : target
end

.guard(&block) ⇒ Object

*_impl providers only need provide the implementation if it can support it. Otherwise, this method will detect that the method is missing.



238
239
240
241
242
# File 'lib/image_voodoo.rb', line 238

def self.guard(&block)
  block.call
rescue NoMethodError => e
  "Unimplemented Feature: #{e}"
end

.image_from_url(source) ⇒ Object



102
103
104
105
106
107
108
109
110
# File 'lib/image_voodoo/awt.rb', line 102

def self.image_from_url(source)
  image = Toolkit.default_toolkit.create_image(URL.new(source))
  tracker = MediaTracker.new(Label.new(''))
  tracker.addImage(image, 0)
  tracker.waitForID(0)
  image
rescue IOException, MalformedURLException
  raise ArgumentError, "Trouble retrieving image: #{$!.message}"
end

.new_image(width, height, file_name) ⇒ Object

Creates a new (empty) image with a file name specified.



211
212
213
214
# File 'lib/image_voodoo.rb', line 211

def self.new_image(width, height, file_name)
  image = guard { new_image_impl(width, height, file_name) }
  block_given? ? yield(image) : image
end

.with_bytes(bytes) ⇒ Object Also known as: with_image_from_memory

A top-level image loader reads bytes and then yields/returns the image.



225
226
227
228
229
# File 'lib/image_voodoo.rb', line 225

def self.with_bytes(bytes)
  bytes = bytes.to_java_bytes if bytes.is_a? String
  image = guard { with_bytes_impl(bytes) }
  block_given? ? yield(image) : image
end

.with_image(path) ⇒ Object

A top-level image loader opens path and then yields/returns the image.

Raises:

  • (ArgumentError)


217
218
219
220
221
222
# File 'lib/image_voodoo.rb', line 217

def self.with_image(path)
  raise ArgumentError, "file does not exist: #{path}" unless File.file?(path)

  image = guard { with_image_impl(JFile.new(path)) }
  image && block_given? ? yield(image) : image
end

Instance Method Details

#adjust_brightness(scale, offset) ⇒ Object

Adjusts the brightness of each pixel in image by the following formula: new_pixel = pixel * scale + offset



67
68
69
70
# File 'lib/image_voodoo.rb', line 67

def adjust_brightness(scale, offset)
  image = guard { adjust_brightness_impl(scale, offset) }
  block_given? ? yield(image) : image
end

#alpha(rgb) ⇒ Object

Converts rgb hex color value to an alpha value an yields/returns the new image.



74
75
76
77
# File 'lib/image_voodoo.rb', line 74

def alpha(rgb)
  target = guard { alpha_impl(rgb) }
  block_given? ? yield(target) : target
end

#bytes(format) ⇒ Object

Get current image bytes as a String using provided format. Format parameter is the informal name of an image type - for instance, “bmp” or “jpg”. If the backend is AWT the types available are listed in javax.imageio.ImageIO.getWriterFormatNames()



83
84
85
86
# File 'lib/image_voodoo.rb', line 83

def bytes(format)
  java_bytes = guard { bytes_impl(format) }
  String.from_java_bytes java_bytes
end

#color_at(x, y) ⇒ Object

AWT-only Return awt Color object.



72
73
74
# File 'lib/image_voodoo/awt.rb', line 72

def color_at(x, y)
  Color.new(pixel(x, y))
end

#correct_orientationObject

If current image was taken by a phone it might save the orientation in format it was physically taken and added IFD0 Orientation information instead of rotating it. This method will perform that rotation based on Orientation metadata.



92
93
94
95
# File 'lib/image_voodoo.rb', line 92

def correct_orientation
  target = guard { correct_orientation_impl }
  block_given? ? yield(target) : target
end

#crop(x, y, width, height) ⇒ Object

crops part of an image



98
99
100
101
# File 'lib/image_voodoo.rb', line 98

def crop(x, y, width, height)
  target = with_crop(x, y, x + width, y + height)
  block_given? ? yield(target) : target
end

#cropped_thumbnail(size) ⇒ Object

Creates a square thumbnail of the image cropping the longest edge to match the shortest edge, resizes to size, and yields/returns the new image.



105
106
107
108
109
# File 'lib/image_voodoo.rb', line 105

def cropped_thumbnail(size)
  l, t, r, b = calculate_thumbnail_dimensions
  target = with_crop(l, t, r, b).thumbnail(size)
  block_given? ? yield(target) : target
end

#flip_horizontallyObject

Flips the image horizontally and yields/returns the new image.



121
122
123
124
# File 'lib/image_voodoo.rb', line 121

def flip_horizontally
  target = guard { flip_horizontally_impl }
  block_given? ? yield(target) : target
end

#flip_verticallyObject

Flips the image vertically and yields/returns the new image.



127
128
129
130
# File 'lib/image_voodoo.rb', line 127

def flip_vertically
  target = guard { flip_vertically_impl }
  block_given? ? yield(target) : target
end

#formatObject

Returns detected image format from binary representation of input data as upper case string. Eg. JPEG, BMP, PNG. For GWT image representation compatibility method name is :format. It also accepts block and returns format as first block argument. When format not detected or not set it returns nil



270
271
272
# File 'lib/image_voodoo.rb', line 270

def format
  @format && block_given? ? yield(@format) : @format
end

#greyscaleObject Also known as: grayscale

Creates a grayscale version of image and yields/returns the new image.



133
134
135
136
# File 'lib/image_voodoo.rb', line 133

def greyscale
  target = guard { greyscale_impl }
  block_given? ? yield(target) : target
end

#guard(&block) ⇒ Object



244
245
246
# File 'lib/image_voodoo.rb', line 244

def guard(&block)
  ImageVoodoo.guard(&block)
end

#heightObject

Returns the height of the image, in pixels.



249
250
251
# File 'lib/image_voodoo.rb', line 249

def height
  @src.height
end

#i_am_feeling_luckyObject

GAE Automatically adjust contrast and color levels.



18
19
20
# File 'lib/image_voodoo/gae.rb', line 18

def i_am_feeling_lucky
  transform(ImagesServiceFactory.make_im_feeling_lucky)
end

#metadataObject

Extracts metadata from an image.



140
141
142
# File 'lib/image_voodoo.rb', line 140

def 
  guard {  }
end

#negativeObject

Creates a negative and yields/returns the new image.



145
146
147
148
# File 'lib/image_voodoo.rb', line 145

def negative
  target = guard { negative_impl }
  block_given? ? yield(target) : target
end

#paint(src = dup_src) {|src.graphics, src| ... } ⇒ Object

AWT-only paint/render to the source

Yields:

  • (src.graphics, src)


86
87
88
89
90
# File 'lib/image_voodoo/awt.rb', line 86

def paint(src=dup_src)
  yield src.graphics, src
  src.graphics.dispose
  ImageVoodoo.new(@io, src, @format)
end

#pixel(x, y) ⇒ Object

Gets RGB value within the source image at [x, y]. If using AWT backend then consider using color_at as this is a Java signed int value of an unsigned value.



61
62
63
# File 'lib/image_voodoo.rb', line 61

def pixel(x, y)
  @src.getRGB(x, y)
end

#preview(&block) ⇒ Object

AWT-only Creates a viewable frame displaying current image within it.



77
78
79
80
81
82
83
# File 'lib/image_voodoo/awt.rb', line 77

def preview(&block)
  frame = JFrame.new('Preview')
  frame.add_window_listener WindowClosed.new(block)
  frame.set_bounds 0, 0, width + 20, height + 40
  frame.add JImagePanel.new(self, 10, 10)
  frame.visible = true
end

#resize(width, height) ⇒ Object

Resizes the image to width and height and yields/returns the new image.



164
165
166
167
168
169
# File 'lib/image_voodoo.rb', line 164

def resize(width, height)
  target = guard { resize_impl(width, height) }
  block_given? ? yield(target) : target
rescue java.lang.Exception => e # figure out why this is here at all?
  raise ArgumentError, e.message
end

#rotate(angle) ⇒ Object

Rotates the image by angle (specified in degrees).



172
173
174
175
# File 'lib/image_voodoo.rb', line 172

def rotate(angle)
  target = guard { rotate_impl(to_radians(angle)) }
  block_given? ? yield(target) : target
end

#save(file) ⇒ Object

Saves the image out to path. Changing the file extension will convert the file type to the appropriate format.



179
180
181
182
183
184
185
186
# File 'lib/image_voodoo.rb', line 179

def save(file)
  format = File.extname(file)
  return false if format == ''

  format = format[1..-1].downcase
  guard { save_impl(format, JFile.new(file)) }
  true
end

#save_impl(format, file) ⇒ Object

Save using the format string (jpg, gif, etc..) to the open Java File instance passed in.



179
180
181
# File 'lib/image_voodoo/awt.rb', line 179

def save_impl(format, file)
  write_new_image format, FileImageOutputStream.new(file)
end

#scale(ratio) ⇒ Object

Resize (scale) the current image by the provided ratio and yield/return the new image.



190
191
192
193
194
# File 'lib/image_voodoo.rb', line 190

def scale(ratio)
  new_width, new_height = (width * ratio).to_i, (height * ratio).to_i
  target = resize(new_width, new_height)
  block_given? ? yield(target) : target
end

#thumbnail(size) ⇒ Object

Creates a proportional thumbnail of the image scaled so its longest edge is resized to size and yields/returns the new image.



198
199
200
201
# File 'lib/image_voodoo.rb', line 198

def thumbnail(size)
  target = scale(size.to_f / (width > height ? width : height))
  block_given? ? yield(target) : target
end

#to_javaObject

Returns the underlying Java class associated with this object. Note: Depending on whether you are using AWT or GAE/J you will get a totally different Java class. So caveat emptor!



261
262
263
# File 'lib/image_voodoo.rb', line 261

def to_java
  @src
end

#to_radians(degrees) ⇒ Object



274
275
276
# File 'lib/image_voodoo.rb', line 274

def to_radians(degrees)
  degrees * Math::PI / 180
end

#widthObject

Returns the width of the image, in pixels.



254
255
256
# File 'lib/image_voodoo.rb', line 254

def width
  @src.width
end

#with_crop(left, top, right, bottom) ⇒ Object

Crops an image to left, top, right, and bottom and then yields/returns the new image.



205
206
207
208
# File 'lib/image_voodoo.rb', line 205

def with_crop(left, top, right, bottom)
  image = guard { with_crop_impl(left, top, right, bottom) }
  block_given? ? yield(image) : image
end