Modified: trunk/image_voodoo/bin/image_voodoo (996 => 997)
--- trunk/image_voodoo/bin/image_voodoo 2008-05-19 13:36:43 UTC (rev 996)
+++ trunk/image_voodoo/bin/image_voodoo 2008-05-19 22:17:57 UTC (rev 997)
@@ -27,16 +27,30 @@
opts.separator ""
opts.separator "Actions:"
+ opts.on("-b", "--brightness SCALE,OFFSET", "Adjust brightness") do |args|
+ scale, offset = args.split(/\,/i).map {|v| v.to_f}
+ opts.usage "You need to specify proper scale and offset" unless scale && offset
+ actions << lambda {|img| img.adjust_brightness(scale, offset) }
+ end
+
opts.on("-d", "--dimensions", "Print the image dimensions") do
actions << lambda {|img| puts "#{img.width}x#{img.height}"; img }
end
+ opts.on("-g", "--greyscale", "Convert image to greyscale") do
+ actions << lambda {|img| img.greyscale }
+ end
+
+ opts.on("-n", "--negative", "Make a negative out of the image") do
+ actions << lambda {|img| img.negative }
+ end
+
opts.on("-s", "--save FILENAME", "Save the results to a new file") do |f|
actions << lambda {|img| img.save(f); img }
end
opts.on("-t", "--thumbnail SIZE", Integer, "Create a thumbnail of the given size") do |size|
- actions << lambda {|img| result = nil; img.thumbnail(size) {|img2| result = img2 }; result }
+ actions << lambda {|img| img.thumbnail(size) }
end
opts.on("-p", "--preview", "Preview the image. Close the frame window",
@@ -60,7 +74,7 @@
opts.on("-r", "--resize WIDTHxHEIGHT", "Create a new image with the specified", "dimensions") do |dim|
width, height = dim.split(/x/i).map {|v| v.to_i}
opts.usage "You need to specify proper dimensions" unless width && width > 0 && height && height > 0
- actions << lambda {|img| result = nil; img.resize(width,height) {|img2| result = img2}; result }
+ actions << lambda {|img| img.resize(width,height) }
end
opts.on_tail("-h", "--help", "Show this message") do
Modified: trunk/image_voodoo/lib/image_voodoo.rb (996 => 997)
--- trunk/image_voodoo/lib/image_voodoo.rb 2008-05-19 13:36:43 UTC (rev 996)
+++ trunk/image_voodoo/lib/image_voodoo.rb 2008-05-19 22:17:57 UTC (rev 997)
@@ -12,20 +12,25 @@
# end
# end
class ImageVoodoo
- VERSION = "0.1"
-
include Java
import java.awt.RenderingHints
+ import java.awt.color.ColorSpace
import java.awt.geom.AffineTransform
+ import java.awt.image.ByteLookupTable
+ import java.awt.image.ColorConvertOp
+ import java.awt.image.LookupOp
+ import java.awt.image.RescaleOp
import java.awt.image.BufferedImage
- import javax.imageio.ImageIO
- import javax.swing.JFrame
-
JFile = java.io.File
BAIS = java.io.ByteArrayInputStream
BAOS = java.io.ByteArrayOutputStream
+ import javax.imageio.ImageIO
+ import javax.swing.JFrame
+ NEGATIVE_OP = LookupOp.new(ByteLookupTable.new(0, (0...254).to_a.reverse.to_java(:byte)), nil)
+ GREY_OP = ColorConvertOp.new(ColorSpace.getInstance(ColorSpace::CS_GRAY), nil)
+
class JImagePanel < javax.swing.JPanel
def initialize(image, x=0, y=0)
super()
@@ -47,13 +52,22 @@
@src = ""
end
+ # Foreach pixel new_pixel = pixel * scale + offset
+ def adjust_brightness(scale, offset)
+ image = ImageVoodoo.new internal_transform(RescaleOp.new(scale, offset, nil))
+ block_given? ? yield(image) : image
+ end
+
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
- with_crop(l, t, r, b) do |img|
- img.thumbnail(size) { |thumb| yield thumb }
+ with_crop(l, t, r, b) do |image|
+ image.thumbnail(size) do |thumb|
+ target = ImageVoodoo.new target
+ block_given? ? yield(target) : target
+ end
end
end
@@ -69,9 +83,9 @@
@src
end
- def color_type
- return BufferedImage::TYPE_INT_ARGB if @src.color_model.has_alpha
- BufferedImage::TYPE_INT_RGB
+ def negative
+ image = ImageVoodoo.new internal_transform(NEGATIVE_OP)
+ block_given? ? yield(image) : image
end
def resize(width, height)
@@ -79,30 +93,21 @@
graphics = target.graphics
graphics.set_rendering_hint(RenderingHints::KEY_INTERPOLATION,
RenderingHints::VALUE_INTERPOLATION_BICUBIC)
-
w_scale = width.to_f / @src.width
h_scale = height.to_f / @src.height
-
transform = AffineTransform.get_scale_instance w_scale, h_scale
-
graphics.draw_rendered_image @src, transform
graphics.dispose
- yield ImageVoodoo.new(target)
+ target = ImageVoodoo.new target
+ block_given? ? yield(target) : target
rescue NativeException => ne
raise ArgumentError, ne.message
end
def greyscale
- target = BufferedImage.new(width, height, BufferedImage::TYPE_USHORT_GRAY)
- graphics = target.graphics
- graphics.set_rendering_hint(RenderingHints::KEY_INTERPOLATION,
- RenderingHints::VALUE_INTERPOLATION_BICUBIC)
-
- graphics.draw_rendered_image @src, nil
- graphics.dispose
-
- yield ImageVoodoo.new(target)
+ image = ImageVoodoo.new internal_transform(GREY_OP)
+ block_given? ? yield(image) : image
end
def save(file)
@@ -138,7 +143,10 @@
def scale(ratio)
new_width = (width * ratio).to_i
new_height = (height * ratio).to_i
- resize(new_width, new_height) {|image| yield image }
+ resize(new_width, new_height) do |image|
+ target = ImageVoodoo.new image
+ block_given? ? yield(target) : target
+ end
end
def thumbnail(size)
@@ -146,23 +154,53 @@
end
def with_crop(left, top, right, bottom)
- subimage = @src.get_subimage(left, top, right - left, bottom - top)
- yield ImageVoodoo.new(subimage)
+ image = ImageVoodoo.new(@src.get_subimage(left, top, right-left, bottom-top))
+ block_given? ? yield(image) : image
end
+ # TODO: Figure out how to determine whether source has alpha or not
+ def self.from_url(source)
+ url = ""
+ 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 = BufferedImage.new(image.getWidth, image.getHeight, BufferedImage::TYPE_INT_RGB)
+ graphics = target.graphics
+ graphics.drawImage(image, 0, 0, nil)
+ graphics.dispose
+ target = ImageVoodoo.new target
+ block_given? ? yield(target) : target
+ rescue java.io.IOException, java.net.MalformedURLException
+ raise ArgumentError.new "Trouble retrieving image: #{$!.message}"
+ end
+
def self.with_image(file)
readers = ImageIO.getImageReadersBySuffix(File.extname(file)[1..-1])
raise TypeError, "unrecognized format for #{file}" unless readers.hasNext
- image = ImageIO.read(JFile.new(file))
- yield ImageVoodoo.new(image)
+ image = ImageVoodoo.new ImageIO.read(JFile.new(file))
+ block_given? ? yield(image) : image
rescue NativeException => ne
nil
end
def self.with_bytes(bytes)
bytes = bytes.to_java_bytes if String === bytes
+ image = ImageVoodoo.new ImageIO.read(BAIS.new(bytes))
+ block_given? ? yield(image) : image
+ end
- image = ImageIO.read(BAIS.new(bytes))
- yield ImageVoodoo.new(image)
+ private
+ def color_type
+ return BufferedImage::TYPE_INT_ARGB if @src.color_model.has_alpha
+ BufferedImage::TYPE_INT_RGB
end
+
+ def internal_transform(operation, target=BufferedImage.new(width, height, color_type))
+ graphics = target.graphics
+ graphics.drawImage(@src, 0, 0, nil)
+ graphics.drawImage(operation.filter(target, nil), 0, 0, nil)
+ graphics.dispose
+ target
+ end
end