class Magick::Image
Ruby-level Magick::Image
methods
Public Class Methods
# File lib/rmagick4j/image.rb, line 22 def self.allocate(*args, &add) info = Info.new(&add) if args.length == 1 case args[0] when String then # TODO Respect Dir.getwd name = args[0] @image = Magick4J.ImageDatabase.createDefault(name, info._info) || Magick4J.MagickImage.new(java.io.File.new(name)) when Magick4J.MagickImage then @image = args[0] when Image then @image = args[0]._image else raise ArgumentError, "The argument just can be a String, a MagickImage or an Image instance." end else @image = Magick4J.MagickImage.new(args[0], args[1], info._info) if args.length == 3 args[2].fill(self) end end end
# File lib/rmagick4j/image.rb, line 4 def self.from_blob(blob, &add) # TODO multiple images in file [Image.from_image(Magick4J.MagickImage.from_blob(blob.to_java_bytes), &add)] end
# File lib/rmagick4j/image.rb, line 15 def self.from_image(image, &add) raise ArgumentError, 'First parameter must be a MagickImage instance.' unless image.is_a? Magick4J.MagickImage magick_image = Image.new(image.getWidth(), image.getHeight(), &add) magick_image._image = image magick_image end
# File lib/rmagick4j/image.rb, line 194 def initialize(columns, rows, fill=nil, &info_block) info = Info.new(&info_block) @image = Magick4J.MagickImage.new(columns, rows, info._info) fill.fill(self) if fill.respond_to? :fill end
# File lib/rmagick4j/image.rb, line 9 def self.read(file, &add) info = Info.new(&add) image = Magick4J.ImageDatabase.createDefault(file.to_s, info._info) || Magick4J.MagickImage.new(java.io.File.new(file.to_s)) [Image.from_image(image,&add)] end
Public Instance Methods
# File lib/rmagick4j/image.rb, line 174 def _image @image end
# File lib/rmagick4j/image.rb, line 178 def _image=(new_image) @image = new_image end
# File lib/rmagick4j/image.rb, line 186 def _info @info end
# File lib/rmagick4j/image.rb, line 190 def _info=(new_info) @info = new_info end
Provide an alternate version of Draw#annotate
, for folks who want to find it in this class.
# File lib/RMagick.rb, line 761 def annotate(draw, width, height, x, y, text, &block) check_destroyed draw.annotate(self, width, height, x, y, text, &block) self end
# File lib/rmagick4j/image.rb, line 45 def background_color @image.getBackgroundColor end
# File lib/rmagick4j/image.rb, line 49 def background_color=(value) raise TypeError, "argument must be color name or pixel (#{value.class} given)" unless value.is_a?(String) || value.is_a?(Pixel) value = Pixel.from_color(value) if value.is_a?(String) @image.setBackgroundColor(value) end
# File lib/rmagick4j/image.rb, line 55 def blur @image.getBlur end
# File lib/rmagick4j/image.rb, line 59 def blur=(value) raise TypeError, "no implicit conversion to float from #{value.class.to_s.downcase}" unless value.is_a? Numeric @image.setBlur(value) end
# File lib/rmagick4j/image.rb, line 64 def blur_image(radius=0.0, sigma=1.0) # Swap order on purpose. I wanted them the other way around in Magick4J. Image.from_image(Effects.BlurEffect.new(radius,sigma).apply(_image)) end
# File lib/rmagick4j/image.rb, line 69 def change_geometry(geometry) geometry = Geometry.from_s(geometry.to_s) unless geometry.is_a? Geometry index = if geometry.flag.nil? 0 else geometry.flag._val end width_distance = geometry.width.nil? ? JRelativeWidthDistance.new : JWidthDistances[index].new(geometry.width) height_distance = geometry.height.nil? ? JRelativeHeightDistance.new : JHeightDistances[index].new(geometry.height) geometry = JGeometry.new(width_distance, height_distance, geometry.x, geometry.y) yield geometry.calculate_width(self._image), geometry.calculate_height(self._image), self end
# File lib/rmagick4j/image.rb, line 89 def charcoal(radius=0.0, sigma=1.0) Image.from_image(Effects.CharcoalEffect.new(radius,sigma).apply(_image)) end
Set all pixels that are neighbors of x,y and are not the border color to the fill color
# File lib/RMagick.rb, line 783 def color_fill_to_border(x, y, fill) color_flood_fill(border_color, fill, x, y, Magick::FillToBorderMethod) end
Set all pixels that have the same color as the pixel at x,y and are neighbors to the fill color
# File lib/RMagick.rb, line 776 def color_floodfill(x, y, fill) target = pixel_color(x, y) color_flood_fill(target, fill, x, y, Magick::FloodfillMethod) end
Set the color at x,y
# File lib/RMagick.rb, line 768 def color_point(x, y, fill) f = copy f.pixel_color(x, y, fill) return f end
Set all pixels to the fill color. Very similar to Image#erase!
Accepts either String or Pixel
arguments
# File lib/RMagick.rb, line 789 def color_reset!(fill) save = background_color # Change the background color _outside_ the begin block # so that if this object is frozen the exeception will be # raised before we have to handle it explicitly. self.background_color = fill begin erase! ensure self.background_color = save end self end
# File lib/rmagick4j/image.rb, line 93 def columns @image.getWidth end
# File lib/rmagick4j/image.rb, line 97 def composite(*args) # image, x, y, composite_op args[0] = args[0]._image args.map! {|arg| arg.is_a?(Enum) ? arg._val : arg} Image.from_image(@image.composited(*args)) end
# File lib/rmagick4j/image.rb, line 104 def copy Image.from_image(@image.clone) end
# File lib/rmagick4j/image.rb, line 108 def crop(*args) copy.crop!(*args) end
# File lib/rmagick4j/image.rb, line 112 def crop!(*args) # gravity, x, y, width, height, reset_offset # Defaults. gravity = nil x = y = -1 reset_offset = false # Find available args. if args.first.is_a? GravityType gravity = args.shift._val end if [FalseClass, TrueClass].member? args.last.class reset = args.pop end if args.length == 4 x, y = args[0..1] end width, height = args[-2..-1] # Call Java. # TODO Why wouldn't we reset offset information? Do we need to use that? @image = unless gravity.nil? if x == -1 || y == -1 @image.crop(gravity, width, height) else @image.crop(gravity, x, y, width, height) end else @image.crop(x,y,width,height) end self end
Preserve aliases used < RMagick 2.0.1
Used by ImageList
methods - see ImageList#cur_image
# File lib/RMagick.rb, line 804 def cur_image self end
# File lib/rmagick4j/image.rb, line 143 def display @image.display self end
Iterate over IPTC
record number:dataset tags, yield for each non-nil dataset
# File lib/RMagick.rb, line 866 def each_iptc_dataset Magick::IPTC.constants.each do |record| rec = Magick::IPTC.const_get(record) rec.constants.each do |dataset| data_field = get_iptc_dataset(rec.const_get(dataset)) yield(dataset, data_field) unless data_field.nil? end end nil end
Thanks to Russell Norris!
# File lib/RMagick.rb, line 809 def each_pixel get_pixels(0, 0, columns, rows).each_with_index do |p, n| yield(p, n%columns, n/columns) end self end
# File lib/rmagick4j/image.rb, line 148 def edge(radius=0.0) Image.from_image(Effects.EdgeEffect.new(radius).apply(_image)) end
# File lib/rmagick4j/image.rb, line 152 def erase! @image.erase end
# File lib/rmagick4j/image.rb, line 318 def file_path(file) @image.file_path(file) end
# File lib/rmagick4j/image.rb, line 314 def file_type(file) @image.file_type(file) end
# File lib/rmagick4j/image.rb, line 165 def flip copy.flip end
# File lib/rmagick4j/image.rb, line 169 def flip! @image.flip self end
# File lib/rmagick4j/image.rb, line 156 def format @image.getFormat end
# File lib/rmagick4j/image.rb, line 160 def format= format @image.setFormat(format) self end
Retrieve EXIF data by entry or all. If one or more entry names specified, return the values associated with the entries. If no entries specified, return all entries and values. The return value is an array of [name,value] arrays.
# File lib/RMagick.rb, line 820 def get_exif_by_entry(*entry) ary = Array.new if entry.length == 0 exif_data = self['EXIF:*'] if exif_data exif_data.split("\n").each { |exif| ary.push(exif.split('=')) } end else get_exif_by_entry() # ensure properties is populated with exif data entry.each do |name| rval = self["EXIF:#{name}"] ary.push([name, rval]) end end return ary end
Retrieve EXIF data by tag number or all tag/value pairs. The return value is a hash.
# File lib/RMagick.rb, line 838 def get_exif_by_number(*tag) hash = Hash.new if tag.length == 0 exif_data = self['EXIF:!'] if exif_data exif_data.split("\n").each do |exif| tag, value = exif.split('=') tag = tag[1,4].hex hash[tag] = value end end else get_exif_by_number() # ensure properties is populated with exif data tag.each do |num| rval = self['#%04X' % num.to_i] hash[num] = rval == 'unknown' ? nil : rval end end return hash end
Retrieve IPTC
information by record number:dataset tag constant defined in Magick::IPTC
, above.
# File lib/RMagick.rb, line 861 def get_iptc_dataset(ds) self['IPTC:'+ds] end
# File lib/rmagick4j/image.rb, line 182 def implode(amount=0.5) Image.from_image(Effects.ImplodeEffect.new(amount).apply(_image)) end
(Thanks to Al Evans for the suggestion.)
# File lib/RMagick.rb, line 890 def level(black_point=0.0, white_point=nil, gamma=nil) black_point = Float(black_point) white_point ||= Magick::QuantumRange - black_point white_point = Float(white_point) gamma_arg = gamma gamma ||= 1.0 gamma = Float(gamma) if gamma.abs > 10.0 || white_point.abs <= 10.0 || white_point.abs < gamma.abs gamma, white_point = white_point, gamma unless gamma_arg white_point = Magick::QuantumRange - black_point end end return level2(black_point, white_point, gamma) end
# File lib/rmagick4j/image.rb, line 200 def matte @image.getMatte end
# File lib/rmagick4j/image.rb, line 204 def matte= matte @image.setMatte(matte) end
Make transparent any neighbor pixel that is not the border color.
# File lib/RMagick.rb, line 944 def matte_fill_to_border(x, y) f = copy f.opacity = Magick::OpaqueOpacity unless f.matte f.matte_flood_fill(border_color, TransparentOpacity, x, y, FillToBorderMethod) end
Make transparent any pixel that matches the color of the pixel at (x,y) and is a neighbor.
# File lib/RMagick.rb, line 935 def matte_floodfill(x, y) f = copy f.opacity = OpaqueOpacity unless f.matte target = f.pixel_color(x, y) f.matte_flood_fill(target, TransparentOpacity, x, y, FloodfillMethod) end
Make the pixel at (x,y) transparent.
# File lib/RMagick.rb, line 915 def matte_point(x, y) f = copy f.opacity = OpaqueOpacity unless f.matte pixel = f.pixel_color(x,y) pixel.opacity = TransparentOpacity f.pixel_color(x, y, pixel) return f end
Make transparent all pixels that are the same color as the pixel at (x, y).
# File lib/RMagick.rb, line 926 def matte_replace(x, y) f = copy f.opacity = OpaqueOpacity unless f.matte target = f.pixel_color(x, y) f.transparent(target) end
Make all pixels transparent.
# File lib/RMagick.rb, line 952 def matte_reset! self.opacity = Magick::TransparentOpacity self end
# File lib/rmagick4j/image.rb, line 208 def negate(grayscale=false) Image.from_image(Effects.NegateEffect.new(grayscale).apply(_image)) end
# File lib/rmagick4j/image.rb, line 212 def normalize Image.from_image(Effects.NormalizeEffect.new().apply(_image)) end
# File lib/rmagick4j/image.rb, line 216 def quantize(number_colors=256, colorspace=RGBColorspace, dither=true, tree_depth=0, measure_error=false) Image.from_image(@image.quantized(number_colors, colorspace._val, dither, tree_depth, measure_error)) end
# File lib/rmagick4j/image.rb, line 220 def raise(width=6, height=6, raise=true) Image.from_image(@image.raised(width, height, raise)) end
# File lib/rmagick4j/image.rb, line 224 def remap # TODO: Implement. Just here to avoid warning in RMagick 2.9 file. end
Corresponds to ImageMagick's -resample option
# File lib/RMagick.rb, line 958 def resample(x_res=72.0, y_res=nil) y_res ||= x_res width = x_res * columns / x_resolution + 0.5 height = y_res * rows / y_resolution + 0.5 self.x_resolution = x_res self.y_resolution = y_res resize(width, height) end
# File lib/rmagick4j/image.rb, line 228 def resize(*args) copy.resize!(*args) end
# File lib/rmagick4j/image.rb, line 232 def resize!(*args) @image = if args.length == 1 @image.resized(args[0]) elsif args.length == 2 # It must be 4 nor 2, but two of them are not yet implemented # TODO Implement the other two arguments. # arg[0] --> new_width # arg[1] --> new_height # arg[2] --> filter=LanczosFilter # arg[3] --> support=1.0 @image.resized(args[0],args[1]) else Kernel.raise ArgumentError, "wrong number of parameters(#{args.length} for 1 or 4)" end self end
Force an image to exact dimensions without changing the aspect ratio. Resize and crop if necessary. (Thanks to Jerett Taylor!)
# File lib/RMagick.rb, line 969 def resize_to_fill(ncols, nrows=nil, gravity=CenterGravity) copy.resize_to_fill!(ncols, nrows, gravity) end
# File lib/RMagick.rb, line 973 def resize_to_fill!(ncols, nrows=nil, gravity=CenterGravity) nrows ||= ncols if ncols != columns || nrows != rows scale = [ncols/columns.to_f, nrows/rows.to_f].max resize!(scale*columns+0.5, scale*rows+0.5) end crop!(gravity, ncols, nrows, true) if ncols != columns || nrows != rows self end
Convenience method to resize retaining the aspect ratio. (Thanks to Robert Manni!)
# File lib/RMagick.rb, line 989 def resize_to_fit(cols, rows=nil) rows ||= cols change_geometry(Geometry.new(cols, rows)) do |ncols, nrows| resize(ncols, nrows) end end
# File lib/RMagick.rb, line 996 def resize_to_fit!(cols, rows=nil) rows ||= cols change_geometry(Geometry.new(cols, rows)) do |ncols, nrows| resize!(ncols, nrows) end end
# File lib/rmagick4j/image.rb, line 248 def rotate(amount, qualifier=nil) copy.rotate!(amount,qualifier) end
# File lib/rmagick4j/image.rb, line 252 def rotate!(amount, qualifier=nil) if qualifier == '<' && columns < rows @image.rotate(amount) self elsif qualifier == '>' && columns > rows @image.rotate(amount) self elsif qualifier.nil? @image.rotate(amount) self else nil end end
# File lib/rmagick4j/image.rb, line 267 def rows @image.getHeight end
# File lib/rmagick4j/image.rb, line 271 def shade(shading=false,azimuth=30,elevation=30) Image.from_image(Effects.ShadeEffect.new(shading,azimuth,elevation).apply(_image)) end
# File lib/rmagick4j/image.rb, line 275 def solarize(threshold=50) Image.from_image(Effects.SolarizeEffect.new(threshold).apply(_image)) end
# File lib/rmagick4j/image.rb, line 279 def store_pixels(x, y, columns, rows, pixels) ria_size = columns*rows raise IndexError, "not enough elements in array - expecting #{ria_size}, got #{pixels.size}" if pixels.size < ria_size @image.storePixels(x,y,columns,rows,pixels.to_java) end
Replace neighboring pixels to border color with texture pixels
# File lib/RMagick.rb, line 1010 def texture_fill_to_border(x, y, texture) texture_flood_fill(border_color, texture, x, y, FillToBorderMethod) end
Replace matching neighboring pixels with texture pixels
# File lib/RMagick.rb, line 1004 def texture_floodfill(x, y, texture) target = pixel_color(x, y) texture_flood_fill(target, texture, x, y, FloodfillMethod) end
# File lib/rmagick4j/image.rb, line 285 def to_blob(&add) info = Info.new(&add) @image.setFormat(info.format) if info.format String.from_java_bytes(@image.toBlob) end
Construct a view. If a block is present, yield and pass the view object, otherwise return the view object.
# File lib/RMagick.rb, line 1016 def view(x, y, width, height) view = View.new(self, x, y, width, height) if block_given? begin yield(view) ensure view.sync end return nil else return view end end
# File lib/rmagick4j/image.rb, line 291 def watermark(mark, lightness=1.0, saturation=1.0, gravity=nil, x_offset=0, y_offset=0) if gravity.is_a? Numeric # gravity is technically an optional argument in the middle. gravity = nil y_offset = x_offset x_offset = gravity end # TODO Perform watermark. self end
# File lib/rmagick4j/image.rb, line 302 def wave(amplitude=25.0, wavelength=150.0) Image.from_image(Effects.WaveEffect.new(amplitude,wavelength).apply(_image)) end
# File lib/rmagick4j/image.rb, line 306 def write(file, &add) # TODO I'm having trouble finding out how this info is used, so I'll skip using it for now. info = Info.new(&add) # TODO Resolve pwd as needed @image.write(file) self end