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.2'
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.



147
148
149
150
151
152
153
154
155
# File 'lib/image_voodoo.rb', line 147

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.



232
233
234
235
236
# File 'lib/image_voodoo.rb', line 232

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.



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

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.



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

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:



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

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

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



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

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.



115
116
117
118
# File 'lib/image_voodoo.rb', line 115

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.



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

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



264
265
266
# File 'lib/image_voodoo.rb', line 264

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.



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

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

#guard(&block) ⇒ Object



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

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

#heightObject

Returns the height of the image, in pixels.



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

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.



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

def 
  guard {  }
end

#negativeObject

Creates a negative and yields/returns the new image.



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

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.



158
159
160
161
162
163
# File 'lib/image_voodoo.rb', line 158

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



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

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.



173
174
175
176
177
178
179
180
# File 'lib/image_voodoo.rb', line 173

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.



184
185
186
187
188
# File 'lib/image_voodoo.rb', line 184

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.



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

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!



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

def to_java
  @src
end

#to_radians(degrees) ⇒ Object



268
269
270
# File 'lib/image_voodoo.rb', line 268

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

#widthObject

Returns the width of the image, in pixels.



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

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.



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

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