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

Overview

ImageVoodoo

Description

ImageVoodoo is an ImageScience-API-compatible image manipulation library for JRuby.

Examples

Simple block-based examples

ImageVoodoo.with_image(ARGV[0]) do |img|
  img.cropped_thumbnail(100) { |img2| img2.save "CTH.jpg" }
  img.with_crop(100, 200, 400, 600) { |img2| img2.save "CR.jpg" }
  img.thumbnail(50) { |img2| img2.save "TH.jpg" }
  img.resize(100, 150) do |img2|
    img2.save "HEH.jpg"
    img2.save "HEH.png"
  end
end

Non-block return (not image_science compatible)

img = ImageVoodoo.with_image(ARGV) negative_img = img.negative

Defined Under Namespace

Modules: Shapes Classes: AdobeJpegDirectory, BmpHeaderDirectory, CanonMakernoteDirectory, CasioType1MakernoteDirectory, CasioType2MakernoteDirectory, Directory, ExifIFD0Directory, ExifInteropDirectory, ExifSubIFDDirectory, ExifThumbnailDirectory, FujifilmMakernoteDirectory, GifHeaderDirectory, GpsDirectory, 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.8.8"
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,
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Shapes

#as_color, #rect, #rect_rounded, #square, #square_rounded

Constructor Details

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

Returns a new instance of ImageVoodoo.



56
57
58
59
# File 'lib/image_voodoo.rb', line 56

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.



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

def quality
  @quality
end

Class Method Details

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

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



130
131
132
133
# File 'lib/image_voodoo/awt.rb', line 130

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.



113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/image_voodoo/awt.rb', line 113

def self.from_url(source)
  url = java.net.URL.new(source)
  image = java.awt.Toolkit.default_toolkit.create_image(url)
  tracker = java.awt.MediaTracker.new(java.awt.Label.new(""))
  tracker.addImage(image, 0);
  tracker.waitForID(0)
  target = paint(BufferedImage.new(image.width, image.height, RGB)) do |g|
    g.draw_image image, 0, 0, nil
  end
  block_given? ? yield(target) : target
rescue java.io.IOException, java.net.MalformedURLException
  raise ArgumentError.new "Trouble retrieving image: #{$!.message}"
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.



272
273
274
275
276
277
278
# File 'lib/image_voodoo.rb', line 272

def self.guard(&block)
  begin
    return block.call
  rescue NoMethodError => e
    "Unimplemented Feature: #{e}"
  end
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.



256
257
258
259
260
# File 'lib/image_voodoo.rb', line 256

def self.with_bytes(bytes)
  bytes = bytes.to_java_bytes if String === bytes
  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)


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

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

#add_border(options = {}) ⇒ Object

FIXME: Move and rewrite in terms of new shape

AWT (experimental) Add a border to the image and yield/return a new image. The following options are supported:

- width: How thick is the border (default: 3)
- color: Which color is the border (in rrggbb hex value)
- style: etched, raised, plain (default: plain)


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/image_voodoo/awt.rb', line 32

def add_border(options = {})
  border_width = options[:width].to_i || 2
  color = hex_to_color(options[:color]) || hex_to_color("000000")
  style = options[:style]
  style = nil if style.to_sym == :plain
  new_width, new_height = width + 2*border_width, height + 2*border_width
  target = paint(BufferedImage.new(new_width, new_height, color_type)) do |g|
    g.color = color
    if style
      raised = style.to_sym == :raised ? true : false
      g.fill3DRect(0, 0, new_width, new_height, raised)
    else
      g.fill_rect(0, 0, new_width, new_height)
    end
    g.draw_image(@src, nil, border_width, border_width)
  end
  block_given? ? yield(target) : target
end

#adjust_brightness(scale, offset) ⇒ Object

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



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

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.



76
77
78
79
# File 'lib/image_voodoo.rb', line 76

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



88
89
90
91
# File 'lib/image_voodoo.rb', line 88

def bytes(format)
  java_bytes = guard { bytes_impl(format) }
  String.from_java_bytes java_bytes
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.



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

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.



109
110
111
112
113
114
115
116
# File 'lib/image_voodoo.rb', line 109

def cropped_thumbnail(size)
  l, t, r, b, half = 0, 0, width, height, (width - height).abs / 2
  l, r = half, half + height if width > height
  t, b = half, half + width if height > width

  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.



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

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.



131
132
133
134
# File 'lib/image_voodoo.rb', line 131

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



317
318
319
# File 'lib/image_voodoo.rb', line 317

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.



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

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

#guard(&block) ⇒ Object



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

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

#heightObject

Returns the height of the image, in pixels.



287
288
289
# File 'lib/image_voodoo.rb', line 287

def height
  @src.height
end

#i_am_feeling_luckyObject

GAE Automatically adjust contrast and color levels.



15
16
17
# File 'lib/image_voodoo/gae.rb', line 15

def i_am_feeling_lucky
  transform(ImagesServiceFactory.make_im_feeling_lucky)
end

#metadataObject

Extracts metadata from an image.



150
151
152
# File 'lib/image_voodoo.rb', line 150

def 
  guard {  }
end

#negativeObject

Creates a negative and yields/returns the new image.



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

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

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

AWT paint/render to the source

Yields:

  • (src.graphics)


101
102
103
104
105
# File 'lib/image_voodoo/awt.rb', line 101

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

#preview(&block) ⇒ Object

AWT Creates a viewable frame displaying current image within it.



90
91
92
93
94
95
96
# File 'lib/image_voodoo/awt.rb', line 90

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.



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

def resize(width, height)
  target = guard { resize_impl(width, height) }
  block_given? ? yield(target) : target
rescue NativeException => ne
  raise ArgumentError, ne.message
end

#rotate(angle) ⇒ Object

Rotates the image by angle (specified in degrees).



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

def rotate(angle)
  target = guard { rotate_impl(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.



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

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

#scale(ratio) ⇒ Object

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



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

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.



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

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!



305
306
307
# File 'lib/image_voodoo.rb', line 305

def to_java
  @src
end

#widthObject

Returns the width of the image, in pixels.



295
296
297
# File 'lib/image_voodoo.rb', line 295

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.



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

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