summaryrefslogtreecommitdiff
path: root/ruby_1_9_3/ext/tk/lib/tk/image.rb
diff options
context:
space:
mode:
Diffstat (limited to 'ruby_1_9_3/ext/tk/lib/tk/image.rb')
-rw-r--r--ruby_1_9_3/ext/tk/lib/tk/image.rb395
1 files changed, 395 insertions, 0 deletions
diff --git a/ruby_1_9_3/ext/tk/lib/tk/image.rb b/ruby_1_9_3/ext/tk/lib/tk/image.rb
new file mode 100644
index 0000000000..00bb440d6a
--- /dev/null
+++ b/ruby_1_9_3/ext/tk/lib/tk/image.rb
@@ -0,0 +1,395 @@
+#
+# tk/image.rb : treat Tk image objects
+#
+
+require 'tk'
+
+class TkImage<TkObject
+ include Tk
+
+ TkCommandNames = ['image'.freeze].freeze
+
+ Tk_IMGTBL = TkCore::INTERP.create_table
+
+ (Tk_Image_ID = ['i'.freeze, TkUtil.untrust('00000')]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ Tk_IMGTBL.mutex.synchronize{ Tk_IMGTBL.clear }
+ }
+
+ def self.new(keys=nil)
+ if keys.kind_of?(Hash)
+ name = nil
+ if keys.key?(:imagename)
+ name = keys[:imagename]
+ elsif keys.key?('imagename')
+ name = keys['imagename']
+ end
+ if name
+ if name.kind_of?(TkImage)
+ obj = name
+ else
+ name = _get_eval_string(name)
+ obj = nil
+ Tk_IMGTBL.mutex.synchronize{
+ obj = Tk_IMGTBL[name]
+ }
+ end
+ if obj
+ if !(keys[:without_creating] || keys['without_creating'])
+ keys = _symbolkey2str(keys)
+ keys.delete('imagename')
+ keys.delete('without_creating')
+ obj.instance_eval{
+ tk_call_without_enc('image', 'create',
+ @type, @path, *hash_kv(keys, true))
+ }
+ end
+ return obj
+ end
+ end
+ end
+ (obj = self.allocate).instance_eval{
+ Tk_IMGTBL.mutex.synchronize{
+ initialize(keys)
+ Tk_IMGTBL[@path] = self
+ }
+ }
+ obj
+ end
+
+ def initialize(keys=nil)
+ @path = nil
+ without_creating = false
+ if keys.kind_of?(Hash)
+ keys = _symbolkey2str(keys)
+ @path = keys.delete('imagename')
+ without_creating = keys.delete('without_creating')
+ end
+ unless @path
+ Tk_Image_ID.mutex.synchronize{
+ @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_)
+ Tk_Image_ID[1].succ!
+ }
+ end
+ unless without_creating
+ tk_call_without_enc('image', 'create',
+ @type, @path, *hash_kv(keys, true))
+ end
+ end
+
+ def delete
+ Tk_IMGTBL.mutex.synchronize{
+ Tk_IMGTBL.delete(@id) if @id
+ }
+ tk_call_without_enc('image', 'delete', @path)
+ self
+ end
+ def height
+ number(tk_call_without_enc('image', 'height', @path))
+ end
+ def inuse
+ bool(tk_call_without_enc('image', 'inuse', @path))
+ end
+ def itemtype
+ tk_call_without_enc('image', 'type', @path)
+ end
+ def width
+ number(tk_call_without_enc('image', 'width', @path))
+ end
+
+ def TkImage.names
+ Tk_IMGTBL.mutex.synchronize{
+ Tk.tk_call_without_enc('image', 'names').split.collect!{|id|
+ (Tk_IMGTBL[id])? Tk_IMGTBL[id] : id
+ }
+ }
+ end
+
+ def TkImage.types
+ Tk.tk_call_without_enc('image', 'types').split
+ end
+end
+
+class TkBitmapImage<TkImage
+ def __strval_optkeys
+ super() + ['maskdata', 'maskfile']
+ end
+ private :__strval_optkeys
+
+ def initialize(*args)
+ @type = 'bitmap'
+ super(*args)
+ end
+end
+
+# A photo is an image whose pixels can display any color or be transparent.
+# At present, only GIF and PPM/PGM formats are supported, but an interface
+# exists to allow additional image file formats to be added easily.
+#
+# This class documentation is a copy from the original Tcl/Tk at
+# http://www.tcl.tk/man/tcl8.5/TkCmd/photo.htm with some rewrited parts.
+class TkPhotoImage<TkImage
+ NullArgOptionKeys = [ "shrink", "grayscale" ]
+
+ def _photo_hash_kv(keys)
+ keys = _symbolkey2str(keys)
+ NullArgOptionKeys.collect{|opt|
+ if keys[opt]
+ keys[opt] = None
+ else
+ keys.delete(opt)
+ end
+ }
+ keys.collect{|k,v|
+ ['-' << k, v]
+ }.flatten
+ end
+ private :_photo_hash_kv
+
+ # Create a new image with the given options.
+ # == Examples of use :
+ # === Create an empty image of 300x200 pixels
+ #
+ # image = TkPhotoImage.new(:height => 200, :width => 300)
+ #
+ # === Create an image from a file
+ #
+ # image = TkPhotoImage.new(:file: => 'my_image.gif')
+ #
+ # == Options
+ # Photos support the following options:
+ # * :data
+ # Specifies the contents of the image as a string.
+ # * :format
+ # Specifies the name of the file format for the data.
+ # * :file
+ # Gives the name of a file that is to be read to supply data for the image.
+ # * :gamma
+ # Specifies that the colors allocated for displaying this image in a window
+ # should be corrected for a non-linear display with the specified gamma
+ # exponent value.
+ # * height
+ # Specifies the height of the image, in pixels. This option is useful
+ # primarily in situations where the user wishes to build up the contents of
+ # the image piece by piece. A value of zero (the default) allows the image
+ # to expand or shrink vertically to fit the data stored in it.
+ # * palette
+ # Specifies the resolution of the color cube to be allocated for displaying
+ # this image.
+ # * width
+ # Specifies the width of the image, in pixels. This option is useful
+ # primarily in situations where the user wishes to build up the contents of
+ # the image piece by piece. A value of zero (the default) allows the image
+ # to expand or shrink horizontally to fit the data stored in it.
+ def initialize(*args)
+ @type = 'photo'
+ super(*args)
+ end
+
+ # Blank the image; that is, set the entire image to have no data, so it will
+ # be displayed as transparent, and the background of whatever window it is
+ # displayed in will show through.
+ def blank
+ tk_send_without_enc('blank')
+ self
+ end
+
+ def cget_strict(option)
+ case option.to_s
+ when 'data', 'file'
+ tk_send 'cget', '-' << option.to_s
+ else
+ tk_tcl2ruby(tk_send('cget', '-' << option.to_s))
+ end
+ end
+
+ # Returns the current value of the configuration option given by option.
+ # Example, display name of the file from which <tt>image</tt> was created:
+ # puts image.cget :file
+ def cget(option)
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ cget_strict(option)
+ else
+ begin
+ cget_strict(option)
+ rescue => e
+ if current_configinfo.has_key?(option.to_s)
+ # error on known option
+ fail e
+ else
+ # unknown option
+ nil
+ end
+ end
+ end
+ end
+
+ # Copies a region from the image called source to the image called
+ # destination, possibly with pixel zooming and/or subsampling. If no options
+ # are specified, this method copies the whole of source into destination,
+ # starting at coordinates (0,0) in destination. The following options may be
+ # specified:
+ #
+ # * :from [x1, y1, x2, y2]
+ # Specifies a rectangular sub-region of the source image to be copied.
+ # (x1,y1) and (x2,y2) specify diagonally opposite corners of the rectangle.
+ # If x2 and y2 are not specified, the default value is the bottom-right
+ # corner of the source image. The pixels copied will include the left and
+ # top edges of the specified rectangle but not the bottom or right edges.
+ # If the :from option is not given, the default is the whole source image.
+ # * :to [x1, y1, x2, y2]
+ # Specifies a rectangular sub-region of the destination image to be
+ # affected. (x1,y1) and (x2,y2) specify diagonally opposite corners of the
+ # rectangle. If x2 and y2 are not specified, the default value is (x1,y1)
+ # plus the size of the source region (after subsampling and zooming, if
+ # specified). If x2 and y2 are specified, the source region will be
+ # replicated if necessary to fill the destination region in a tiled fashion.
+ # * :shrink
+ # Specifies that the size of the destination image should be reduced, if
+ # necessary, so that the region being copied into is at the bottom-right
+ # corner of the image. This option will not affect the width or height of
+ # the image if the user has specified a non-zero value for the :width or
+ # :height configuration option, respectively.
+ # * :zoom [x, y]
+ # Specifies that the source region should be magnified by a factor of x
+ # in the X direction and y in the Y direction. If y is not given, the
+ # default value is the same as x. With this option, each pixel in the
+ # source image will be expanded into a block of x x y pixels in the
+ # destination image, all the same color. x and y must be greater than 0.
+ # * :subsample [x, y]
+ # Specifies that the source image should be reduced in size by using only
+ # every xth pixel in the X direction and yth pixel in the Y direction.
+ # Negative values will cause the image to be flipped about the Y or X axes,
+ # respectively. If y is not given, the default value is the same as x.
+ # * :compositingrule rule
+ # Specifies how transparent pixels in the source image are combined with
+ # the destination image. When a compositing rule of <tt>overlay</tt> is set,
+ # the old contents of the destination image are visible, as if the source
+ # image were printed on a piece of transparent film and placed over the
+ # top of the destination. When a compositing rule of <tt>set</tt> is set,
+ # the old contents of the destination image are discarded and the source
+ # image is used as-is. The default compositing rule is <tt>overlay</tt>.
+ def copy(src, *opts)
+ if opts.size == 0
+ tk_send('copy', src)
+ elsif opts.size == 1 && opts[0].kind_of?(Hash)
+ tk_send('copy', src, *_photo_hash_kv(opts[0]))
+ else
+ # for backward compatibility
+ args = opts.collect{|term|
+ if term.kind_of?(String) && term.include?(?\s)
+ term.split
+ else
+ term
+ end
+ }.flatten
+ tk_send('copy', src, *args)
+ end
+ self
+ end
+
+ # Returns image data in the form of a string. The following options may be
+ # specified:
+ # * :background color
+ # If the color is specified, the data will not contain any transparency
+ # information. In all transparent pixels the color will be replaced by the
+ # specified color.
+ # * :format format-name
+ # Specifies the name of the image file format handler to be used.
+ # Specifically, this subcommand searches for the first handler whose name
+ # matches an initial substring of format-name and which has the capability
+ # to read this image data. If this option is not given, this subcommand
+ # uses the first handler that has the capability to read the image data.
+ # * :from [x1, y1, x2, y2]
+ # Specifies a rectangular region of imageName to be returned. If only x1
+ # and y1 are specified, the region extends from (x1,y1) to the bottom-right
+ # corner of imageName. If all four coordinates are given, they specify
+ # diagonally opposite corners of the rectangular region, including x1,y1
+ # and excluding x2,y2. The default, if this option is not given, is the
+ # whole image.
+ # * :grayscale
+ # If this options is specified, the data will not contain color information.
+ # All pixel data will be transformed into grayscale.
+ def data(keys={})
+ tk_split_list(tk_send('data', *_photo_hash_kv(keys)))
+ end
+
+ # Returns the color of the pixel at coordinates (x,y) in the image as a list
+ # of three integers between 0 and 255, representing the red, green and blue
+ # components respectively.
+ def get(x, y)
+ tk_send('get', x, y).split.collect{|n| n.to_i}
+ end
+
+ def put(data, *opts)
+ if opts.empty?
+ tk_send('put', data)
+ elsif opts.size == 1 && opts[0].kind_of?(Hash)
+ tk_send('put', data, *_photo_hash_kv(opts[0]))
+ else
+ # for backward compatibility
+ tk_send('put', data, '-to', *opts)
+ end
+ self
+ end
+
+ def read(file, *opts)
+ if opts.size == 0
+ tk_send('read', file)
+ elsif opts.size == 1 && opts[0].kind_of?(Hash)
+ tk_send('read', file, *_photo_hash_kv(opts[0]))
+ else
+ # for backward compatibility
+ args = opts.collect{|term|
+ if term.kind_of?(String) && term.include?(?\s)
+ term.split
+ else
+ term
+ end
+ }.flatten
+ tk_send('read', file, *args)
+ end
+ self
+ end
+
+ def redither
+ tk_send 'redither'
+ self
+ end
+
+ # Returns a boolean indicating if the pixel at (x,y) is transparent.
+ def get_transparency(x, y)
+ bool(tk_send('transparency', 'get', x, y))
+ end
+
+ # Makes the pixel at (x,y) transparent if <tt>state</tt> is true, and makes
+ # that pixel opaque otherwise.
+ def set_transparency(x, y, state)
+ tk_send('transparency', 'set', x, y, state)
+ self
+ end
+
+ def write(file, *opts)
+ if opts.size == 0
+ tk_send('write', file)
+ elsif opts.size == 1 && opts[0].kind_of?(Hash)
+ tk_send('write', file, *_photo_hash_kv(opts[0]))
+ else
+ # for backward compatibility
+ args = opts.collect{|term|
+ if term.kind_of?(String) && term.include?(?\s)
+ term.split
+ else
+ term
+ end
+ }.flatten
+ tk_send('write', file, *args)
+ end
+ self
+ end
+end