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.8.9'.freeze
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.



51
52
53
54
# File 'lib/image_voodoo.rb', line 51

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.



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

def quality
  @quality
end

Class Method Details

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

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



111
112
113
114
# File 'lib/image_voodoo/awt.rb', line 111

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.



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

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.



229
230
231
232
233
# File 'lib/image_voodoo.rb', line 229

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

.image_from_url(source) ⇒ Object



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

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.



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

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.



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

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)


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

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



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

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.



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

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



81
82
83
84
# File 'lib/image_voodoo.rb', line 81

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.



70
71
72
# File 'lib/image_voodoo/awt.rb', line 70

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.



90
91
92
93
# File 'lib/image_voodoo.rb', line 90

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.



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

def cropped_thumbnail(size)
  l, t, r, b = calculate_thumbnail_dimentions
  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.



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

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.



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

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



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

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.



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

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

#guard(&block) ⇒ Object



235
236
237
# File 'lib/image_voodoo.rb', line 235

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

#heightObject

Returns the height of the image, in pixels.



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

def height
  @src.height
end

#i_am_feeling_luckyObject

GAE Automatically adjust contrast and color levels.



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

def i_am_feeling_lucky
  transform(ImagesServiceFactory.make_im_feeling_lucky)
end

#metadataObject

Extracts metadata from an image.



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

def 
  guard {  }
end

#negativeObject

Creates a negative and yields/returns the new image.



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

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)


84
85
86
87
88
# File 'lib/image_voodoo/awt.rb', line 84

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.



59
60
61
# File 'lib/image_voodoo.rb', line 59

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

#preview(&block) ⇒ Object

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



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

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.



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

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



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

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.



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

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.



175
176
177
# File 'lib/image_voodoo/awt.rb', line 175

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.



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

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.



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

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!



252
253
254
# File 'lib/image_voodoo.rb', line 252

def to_java
  @src
end

#to_radians(degrees) ⇒ Object



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

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

#widthObject

Returns the width of the image, in pixels.



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

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.



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

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