lib/image_voodoo/awt.rb in image_voodoo-0.8.2 vs lib/image_voodoo/awt.rb in image_voodoo-0.8.3
- old
+ new
@@ -1,6 +1,10 @@
+require 'image_voodoo/awt/shapes'
+
class ImageVoodoo
+ include ImageVoodoo::Shapes
+
java_import java.awt.RenderingHints
java_import java.awt.color.ColorSpace
java_import java.awt.geom.AffineTransform
java_import java.awt.image.BufferedImage
java_import java.awt.image.ShortLookupTable
@@ -8,22 +12,20 @@
java_import java.awt.image.LookupOp
java_import java.awt.image.RescaleOp
java_import java.io.ByteArrayInputStream
java_import java.io.ByteArrayOutputStream
java_import javax.imageio.ImageIO
+ java_import javax.imageio.IIOImage
+ java_import javax.imageio.ImageWriteParam
+ java_import javax.imageio.stream.FileImageOutputStream
java_import javax.swing.JFrame
- NEGATIVE_OP = LookupOp.new(ShortLookupTable.new(0, (0...255).to_a.reverse.to_java(:short)), nil)
- GREY_OP = ColorConvertOp.new(ColorSpace.getInstance(ColorSpace::CS_GRAY), nil)
- ARGB = BufferedImage::TYPE_INT_ARGB
- RGB = BufferedImage::TYPE_INT_RGB
- SCALE_SMOOTH = java.awt.Image::SCALE_SMOOTH
-
+ # FIXME: Move and rewrite in terms of new shape
+ ##
#
- # AWT-only (experimental)
- # Add a border to the image and yield/return a new image. The following
- # options are supported:
+ # *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)
#
def add_border(options = {})
@@ -43,69 +45,11 @@
g.draw_image(@src, nil, border_width, border_width)
end
block_given? ? yield(target) : target
end
- def adjust_brightness_impl(scale, offset)
- transform(RescaleOp.new(scale, offset, nil))
- end
-
- # AWT-only
- def alpha_impl(rgb)
- color = hex_to_color(rgb)
- target = paint(BufferedImage.new(width, height, ARGB)) do |g|
- g.set_composite(java.awt.AlphaComposite::Src)
- g.draw_image(@src, nil, 0, 0)
- 0.upto(height-1) do |i|
- 0.upto(width-1) do |j|
- target.setRGB(j, i, 0x8F1C1C) if target.getRGB(j, i) == color.getRGB
- end
- end
- end
- end
-
- def bytes_impl(format)
- out = ByteArrayOutputStream.new
- ImageIO.write(@src, format, out)
- out.to_byte_array
- end
-
- def flip_horizontally_impl
- paint {|g| g.draw_image @src, 0, 0, width, height, width, 0, 0, height, nil}
- end
-
- def flip_vertically_impl
- paint {|g| g.draw_image @src, 0, 0, width, height, 0, height, width, 0, nil}
- end
-
- def greyscale_impl
- transform(GREY_OP)
- end
-
- def negative_impl
- transform(NEGATIVE_OP)
- end
-
- def resize_impl(width, height)
- paint(BufferedImage.new(width, height, color_type)) do |g|
- scaled_image = @src.get_scaled_instance width, height, SCALE_SMOOTH
- g.draw_image scaled_image, 0, 0, nil
- end
- end
-
- #
- # Save using the format string (jpg, gif, etc..) to the open Java File
- # instance passed in.
- #
- def save_impl(format, file)
- ImageIO.write(@src, format, file)
- end
-
- def with_crop_impl(left, top, right, bottom)
- ImageVoodoo.new @src.get_subimage(left, top, right-left, bottom-top)
- end
-
+ ##
#
# A simple swing wrapper around an image voodoo object.
#
class JImagePanel < javax.swing.JPanel
def initialize(image, x=0, y=0)
@@ -125,30 +69,43 @@
def paintComponent(graphics)
graphics.draw_image(@image.to_java, @x, @y, nil)
end
end
+ ImageVoodoo::JImagePanel.__persistent__ = true
+
# Internal class for closing preview window
class WindowClosed
def initialize(block = nil)
@block = block || proc { java.lang.System.exit(0) }
end
def method_missing(meth,*args); end
def windowClosing(event); @block.call; end
end
+ ##
#
- # Creates a viewable frame displaying current image within it.
+ # *AWT* Creates a viewable frame displaying current image within it.
#
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
+ ##
+ # *AWT* paint/render to the source
+ #
+ def paint(src=dup_src)
+ yield src.graphics
+ src.graphics.dispose
+ ImageVoodoo.new src
+ end
+
+ ##
#
# 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.
#
@@ -164,26 +121,40 @@
block_given? ? yield(target) : target
rescue java.io.IOException, java.net.MalformedURLException
raise ArgumentError.new "Trouble retrieving image: #{$!.message}"
end
+ ##
+ # *AWT* Create an image of width x height filled with a single color.
+ #
+ def self.canvas(width, height, rgb='000000')
+ image = ImageVoodoo.new(BufferedImage.new(width, height, ARGB))
+ image.rect(0, 0, width, height, rgb)
+ end
+
+ private
+
+ NEGATIVE_OP = LookupOp.new(ShortLookupTable.new(0, (0...256).to_a.reverse.to_java(:short)), nil)
+ GREY_OP = ColorConvertOp.new(ColorSpace.getInstance(ColorSpace::CS_GRAY), nil)
+ ARGB = BufferedImage::TYPE_INT_ARGB
+ RGB = BufferedImage::TYPE_INT_RGB
+ SCALE_SMOOTH = java.awt.Image::SCALE_SMOOTH
+
def self.with_image_impl(file)
buffered_image = ImageIO.read(file)
buffered_image ? ImageVoodoo.new(buffered_image) : nil
end
def self.with_bytes_impl(bytes)
ImageVoodoo.new ImageIO.read(ByteArrayInputStream.new(bytes))
end
- private
-
#
# Converts a RGB hex value into a java.awt.Color object or dies trying
# with an ArgumentError.
#
- def hex_to_color(rgb)
+ def self.hex_to_color(rgb)
raise ArgumentError.new "hex rrggbb needed" if rgb !~ /[[:xdigit:]]{6,6}/
java.awt.Color.new(rgb[0,2].to_i(16), rgb[2,2].to_i(16), rgb[4,2].to_i(16))
end
@@ -197,11 +168,11 @@
#
# Make a duplicate of the underlying Java src image
#
def dup_src
- BufferedImage.new width, height, color_type
+ BufferedImage.new to_java.color_model, to_java.raster, true, nil
end
#
# Do simple AWT operation transformation to target.
#
@@ -210,14 +181,76 @@
g.draw_image(@src, 0, 0, nil)
g.draw_image(operation.filter(target, nil), 0, 0, nil)
end
end
+ def adjust_brightness_impl(scale, offset)
+ transform(RescaleOp.new(scale, offset, nil))
+ end
+
+ def alpha_impl(rgb)
+ color = hex_to_color(rgb)
+ target = paint(BufferedImage.new(width, height, ARGB)) do |g|
+ g.set_composite(java.awt.AlphaComposite::Src)
+ g.draw_image(@src, nil, 0, 0)
+ 0.upto(height-1) do |i|
+ 0.upto(width-1) do |j|
+ target.setRGB(j, i, 0x8F1C1C) if target.getRGB(j, i) == color.getRGB
+ end
+ end
+ end
+ end
+
+ def bytes_impl(format)
+ out = ByteArrayOutputStream.new
+ write_new_image format, out
+ out.to_byte_array
+ end
+
+ def flip_horizontally_impl
+ paint {|g| g.draw_image @src, 0, 0, width, height, width, 0, 0, height, nil}
+ end
+
+ def flip_vertically_impl
+ paint {|g| g.draw_image @src, 0, 0, width, height, 0, height, width, 0, nil}
+ end
+
+ def greyscale_impl
+ transform(GREY_OP)
+ end
+
+ def negative_impl
+ transform(NEGATIVE_OP)
+ end
+
+ def resize_impl(width, height)
+ paint(BufferedImage.new(width, height, color_type)) do |g|
+ scaled_image = @src.get_scaled_instance width, height, SCALE_SMOOTH
+ g.draw_image scaled_image, 0, 0, nil
+ end
+ end
+
#
- # DRY up drawing setup+teardown
- #
- def paint(src=dup_src)
- yield src.graphics
- src.graphics.dispose
- ImageVoodoo.new src
+ # Save using the format string (jpg, gif, etc..) to the open Java File
+ # instance passed in.
+ #
+ def save_impl(format, file)
+ write_new_image format, FileImageOutputStream.new(file)
+ end
+
+ def with_crop_impl(left, top, right, bottom)
+ ImageVoodoo.new @src.get_subimage(left, top, right-left, bottom-top)
+ end
+
+ def write_new_image(format, stream)
+ writer = ImageIO.getImageWritersByFormatName(format).next
+ writer.output = stream
+
+ param = writer.default_write_param
+ if param.can_write_compressed && @quality
+ param.compression_mode = ImageWriteParam::MODE_EXPLICIT
+ param.compression_quality = @quality
+ end
+
+ writer.write nil, IIOImage.new(@src, nil, nil), param
end
end