Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #==============================================================================
- # ** Copern - Bitmap Color Functions
- #------------------------------------------------------------------------------
- # Version History:
- # 1.0 (09/13/2012) - First release
- #==============================================================================
- # Introduction
- #------------------------------------------------------------------------------
- # This script offers a few methods for recoloring a bitmap, in whole or using
- # a mask, or for modifying the color levels of a bitmap.
- #
- #==============================================================================
- # Requirements
- #------------------------------------------------------------------------------
- # Requires the copernbmcolors.dll in your project folder.
- #
- #==============================================================================
- # Instructions
- #------------------------------------------------------------------------------
- #
- # * Recoloring
- # ------------
- # If you wish to recolor a bitmap to a specific color while maintaining the
- # brightness of the bitmap you may simply use colorify(color) or
- # colorify!(color)
- # For example to give a bitmap an orangish color
- # bitmap.colorify!(Color.new(200, 100, 0))
- #
- # * Recoloring From a Mask
- # ------------------------
- # If you wish to recolor a bitmap to a specific color based on a given mask, use
- # colorify_masked(color, mask_bitmap[, repeat]) or
- # colorify_masked!(color, mask_bitmap[, repeat])
- # The optional boolean parameter, repeat, will repeat the pattern of the mask if
- # it is smaller than the target bitmap.
- #
- # This method takes into account the value and alpha of each pixel on the mask.
- # A value of 128 on the mask will maintain the brightness of the original pixel.
- # A higher value will make the pixels brighter than the original towards max
- # brightness. A lower value will make the pixels darker than the original
- # towards minimum brightness (black in this case). A value of 0 will skip
- # processing of that pixel. The alpha layer of the mask will do as one expects
- # by alpha blending with the original color.
- #
- # * Setting Color Levels
- # ----------------------
- # In order to set the color levels of a bitmap, you will need to create an
- # instance of Color_Levels and define points for the channels you wish to
- # modify. Channels include red, green, blue, alpha, and value. The value channel
- # corresponds to brightness and is applied after the RGB channel.
- # The X in a point is the color value you wish to change ranging from 0 - 255.
- # The Y in a point is the value you want X to become (0 - 255).
- #
- # Lines are created between each point defined in the channel so you don't
- # have to set every point individually. If you want to change only a single
- # value remember that by default, x equals y. You could, for example, set a
- # point at (124, 124), then (125, 200), and finally (126, 126). This way only
- # values of 125 are changed to 200, everything else remains the same.
- #
- # Usable methods in Color Levels are:
- # set_point(channel, x, y)
- #
- # set_points(channel, points)
- # Takes a hash where the keys correlate to X and the values correlate to Y.
- #
- # remove_at(channel, x)
- #
- # remove_range(channel, x_ary)
- # Takes an array of X values.
- #
- # Example using all methods:
- # levels = Color_Levels.new
- # levels.set_point(:red, 60, 150).set_point(:blue, 200, 50)
- # greens = {80 => 45, 100 => 50, 120 => 40}
- # values = {0 => 100, 50 => 100, 110 => 180, 180 => 230}
- # levels.set_points(:green, greens).set_points(:value, values)
- # levels.remove_at(:value, 180).remove_range(:green, [80, 120])
- #
- # After setting the color levels, you can use either bitmap.set_levels(levels)
- # or bitmap.set_levels!(levels).
- #
- #==============================================================================
- # Compatibility
- #------------------------------------------------------------------------------
- #
- # * New variables
- # class Bitmap
- # * Class variables
- # @@colorify
- # @@colorify_masked
- # @@set_levels
- #
- # * New methods
- # class Bitmap
- # def colorify(color)
- # def colorify!(color)
- # def colorify_masked(color, mask, repeat = false)
- # def colorify_masked!(color, mask, repeat = false)
- # def set_levels(levels)
- # def set_levels!(levels)
- # def self.valid_bitmap?(bitmap)
- #
- #==============================================================================
- # Terms of Use
- #------------------------------------------------------------------------------
- #
- # You must give credit to Copern.
- # You may use this script free of charge in FREE and COMMERCIAL games.
- # You may NOT redistribute this script. Scripts that require this must link to
- # the appropriate forum post(s) created by Copern.
- # You may NOT distribute a modified version of this script.
- #
- #==============================================================================
- $imported ||= {}
- $imported[:copern_color_modifications] = true
- module Copern
- module Color_Functs
- VERSION = 1.0
- DLL_NAME =
- #==========================================================================
- # Modify this if you want to change the location of the DLL.
- # Ex 'system\copernbmcolors'
- #--------------------------------------------------------------------------
- 'copernbmcolors'
- #==========================================================================
- end
- module Error
- def self.raise_error(err, obj, msg)
- klass = obj.class.to_s
- stack = caller.slice(1..15)
- stack.each do |i|
- script = i.scan(/\d+/)[0]
- i.sub!(/{\d+}/, $RGSS_SCRIPTS.at(script.to_i)[1]) if script
- end
- raise err, msg % klass << "\n\n#{stack.join("\n")}"
- end
- def self.raise_bitmap(bitmap)
- raise_error(RGSSError, bitmap, "%s is a disposed or invalid bitmap!")
- end
- def self.raise_color(color)
- raise_error(ArgumentError, color, "%s is not a valid color!")
- end
- def self.raise_levels(levels)
- raise_error(ArgumentError, levels, "%s is not a valid color levels instance!")
- end
- end
- end
- #==============================================================================
- # ** Color_Levels
- #------------------------------------------------------------------------------
- # This class ensures proper formatting of points in a color levels graph. The
- # contents are sorted and flattened before being passed to the DLL.
- #==============================================================================
- class Color_Levels
- #--------------------------------------------------------------------------
- # * Class variables
- #--------------------------------------------------------------------------
- @@default = {0 => 0, 255 => 255}.freeze
- #--------------------------------------------------------------------------
- # * initialize
- #--------------------------------------------------------------------------
- def initialize
- #Blue, Green, Red, Alpha, Value
- @channels = Array.new(5) {@@default.dup}
- end
- #--------------------------------------------------------------------------
- # * set_point
- #--------------------------------------------------------------------------
- # Adds or modifies a point in the specified channel.
- #--------------------------------------------------------------------------
- def set_point(channel, x, y)
- return self unless valid_point?(x, y)
- index = get_channel(channel)
- @channels[index][x] = y;
- self
- end
- #--------------------------------------------------------------------------
- # * set_points
- #--------------------------------------------------------------------------
- # Adds or modifies multiple points in the specified channel. Invalid entries
- # are removed prior to merger.
- #--------------------------------------------------------------------------
- def set_points(channel, points)
- return self unless points && points.is_a?(Hash)
- index = get_channel(channel)
- new_points = points.reject {|k, v| !valid_point?(k, v)}
- @channels[index].merge!(new_points)
- self
- end
- #--------------------------------------------------------------------------
- # * remove_at
- #--------------------------------------------------------------------------
- # Removes a point in the specified channel.
- #--------------------------------------------------------------------------
- def remove_at(channel, x)
- return self unless x
- index = get_channel(channel)
- if x == 0 || x == 255
- @channels[index][x] = x
- else
- @channels[index].delete(x)
- end
- self
- end
- #--------------------------------------------------------------------------
- # * remove_range
- #--------------------------------------------------------------------------
- # Removes a range of points in the specified channel.
- #--------------------------------------------------------------------------
- def remove_range(channel, x_range)
- return self unless x_range && x_range.respond_to?(:each)
- x_range.each {|i| remove_at(channel, i)}
- self
- end
- #--------------------------------------------------------------------------
- # * get_sorted_channels
- #--------------------------------------------------------------------------
- # Returns a sorted array for use in the DLL.
- #--------------------------------------------------------------------------
- def sorted_channels
- Array.new(5) {|i| @channels[i].sort.flatten}
- end
- #--------------------------------------------------------------------------
- # * valid_point?
- #--------------------------------------------------------------------------
- # Checks if the given point contains valid color values.
- #--------------------------------------------------------------------------
- def valid_point?(x, y)
- return false unless x && y && x.is_a?(Integer) && y.is_a?(Integer)
- return false if x < 0 || x > 255 || y < 0 || y > 255
- return true
- end
- #--------------------------------------------------------------------------
- # * get_channel
- #--------------------------------------------------------------------------
- # Returns a channel index based on the given channel symbol. Defaults to the
- # red channel if the symbol is not found.
- #--------------------------------------------------------------------------
- def get_channel(channel)
- case channel
- when :blue
- 0
- when :green
- 1
- when :red
- 2
- when :alpha
- 3
- when :value
- 4
- else
- 2
- end
- end
- end
- #==============================================================================
- # ** Bitmap
- #==============================================================================
- class Bitmap
- #--------------------------------------------------------------------------
- # * Class variables
- #--------------------------------------------------------------------------
- @@colorify = Win32API.new(Copern::Color_Functs::DLL_NAME,
- 'colorify', ['l', 'l'], 'l').freeze
- @@colorify_masked = Win32API.new(Copern::Color_Functs::DLL_NAME,
- 'colorifymasked', ['l', 'l', 'l', 'l'], 'l').freeze
- @@set_levels = Win32API.new(Copern::Color_Functs::DLL_NAME,
- 'setlevels', ['l', 'l'], 'l').freeze
- #--------------------------------------------------------------------------
- # * New method: colorify
- #--------------------------------------------------------------------------
- def colorify(color)
- Copern::Error::raise_bitmap(self) if self.disposed?
- Copern::Error::raise_color(color) unless color && color.instance_of?(Color)
- other = self.dup
- @@colorify.call(other.object_id, color.object_id)
- other
- end
- #--------------------------------------------------------------------------
- # * New method: colorify!
- #--------------------------------------------------------------------------
- def colorify!(color)
- Copern::Error::raise_bitmap(self) if self.disposed?
- Copern::Error::raise_color(color) unless color && color.instance_of?(Color)
- @@colorify.call(object_id, color.object_id)
- self
- end
- #--------------------------------------------------------------------------
- # * New method: colorify_masked
- #--------------------------------------------------------------------------
- def colorify_masked(color, mask, repeat = false)
- Copern::Error::raise_bitmap(mask) if self.disposed? || !Bitmap::valid_bitmap?(mask)
- Copern::Error::raise_color(color) unless color && color.instance_of?(Color)
- other = self.dup
- @@colorify_masked.call(other.object_id, mask.object_id, color.object_id, repeat ? 1 : 0)
- other
- end
- #--------------------------------------------------------------------------
- # * New method: colorify_masked!
- #--------------------------------------------------------------------------
- def colorify_masked!(color, mask, repeat = false)
- Copern::Error::raise_bitmap(mask) if self.disposed? || !Bitmap::valid_bitmap?(mask)
- Copern::Error::raise_color(color) unless color && color.instance_of?(Color)
- @@colorify_masked.call(object_id, mask.object_id, color.object_id, repeat ? 1 : 0)
- self
- end
- #--------------------------------------------------------------------------
- # * New method: set_levels
- #--------------------------------------------------------------------------
- def set_levels(levels)
- Copern::Error::raise_bitmap(self) if self.disposed?
- unless levels && levels.instance_of?(Color_Levels)
- Copern::Error::raise_levels(levels)
- end
- channels = levels.sorted_channels
- other = self.dup
- @@set_levels.call(other.object_id, channels.object_id)
- other
- end
- #--------------------------------------------------------------------------
- # * New method: set_levels!
- #--------------------------------------------------------------------------
- def set_levels!(levels)
- Copern::Error::raise_bitmap(self) if self.disposed?
- unless levels && levels.instance_of?(Color_Levels)
- Copern::Error::raise_levels(levels)
- end
- channels = levels.sorted_channels
- @@set_levels.call(object_id, channels.object_id)
- self
- end
- #--------------------------------------------------------------------------
- # * New method: valid_bitmap?
- #--------------------------------------------------------------------------
- def self.valid_bitmap?(bitmap)
- return false unless bitmap && bitmap.instance_of?(Bitmap)
- return false if bitmap.disposed?
- return true
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment