rmagick/bin_magick is an extension of the popular rmagick image processing gem. The extension provides custom methods for easy conversion of color images to binary (monochrome) format. It also introduces in-place versions of some existing Magick::Image methods that, by default, lack an in-place version
The Image class of bin_magick inherits from the Magick::Image class, which allows both Magick::Image and Magick::BinMagick::Image instance methods to be called on a BinMagick::Image object.
bin_magick was developed for the img_to_MK90_bas project, which converts images to Elektronika MK90 executable BASIC scripts, but it may also be useful for similar applications.
- Ruby ver. >= 3.0.0;
- RMagick ver. >= 5.2.0.
Add this line to your application's Gemfile:
gem 'rmagick-bin_magick'
And then execute:
$ bundle install
Or install it yourself as:
$ gem install bin_magick
- Add rmagick-bin_magick to the list of required modules:
require "rmagick/bin_magick"
- Read an image from a file:
image = Magick::BinMagick::Image.from_file("filename.png")
Or initialize an instance based on the existing Magick::Image instance:
image = Magick::BinMagick::Image.new(magick_image_object)
- Call Magick::BinMagick::Image or Magick::Image attribute and instance methods (see the examples section and the reference section for more details).
This example shows how different Magick::BinMagick::Image and Magick::Image instance methods may be combined in one method call chain:
require "rmagick/bin_magick"
# Read an image from a file:
begin
image = Magick::BinMagick::Image.from_file("./data/test_0.png")
rescue Magick::BinMagick::BinMagickError => e
puts e.message
exit
end
image
.level(0, Magick::QuantumRange * 0.95, 0.4) # Adjust levels (a RMagick method).
.crop_border_clr # Crop white border (a BinMagick method).
.fit_to_size!(192, 192) # Resize to fit a 192 x 192 square (a BinMagick method).
.to_binary(64, Magick::NoDitherMethod, "o2x2") # Convert to binary (a BinMagick method).
.write("./data/test_0_result.png") # Save result to a file (a RMagick method).
The code above will produce the following result:
Original image | Result image |
---|---|
You can also use in-place methods:
require "rmagick/bin_magick"
# Read an image from the file './data/test_1.png'
# ...
# Adjust levels (a BinMagick method):
image.level!(0, Magick::QuantumRange, 0.5)
# Crop white border (a BinMagick method):
image.crop_border_clr!
# Resize to fit a 64 x 64 square (a BinMagick method):
image.fit_to_size!(64, 64)
# Convert to binary (a BinMagick method):
image.to_binary!(16)
# Extent to a 120 x 64 rectangle, put image in the center (a BinMagick method):
x_offset = - (120 / 2 - image.width / 2)
y_offset = - (64 - image.height)
image.extent!(120, 64, x_offset, y_offset)
# Save result to a file (a RMagick method):
image.write("./data/test_1_result.png")
The code above will produce the following result:
Original image | Result image |
---|---|
-
height
img.height -> integer
The height of the image in pixels. An alias of the Magick::Image#rows.
-
width
img.width -> integer
The width of the image in pixels. An alias of the Magick::Image#columns.
-
from_file
Magick::BinMagick::Image.from_file(filename) -> image
Reads the first image from the file filename.
Note: an image file can contain multiple images or multiple image layers, but the method always returns the first one. To load a specific image from a file (e.g. a specific frame from an animated GIF), you can use the Magick::Image#read method, and then initialize a BinMagick::Image instance with the BinMagick::Image#new method.
Arguments:
-
filename
An image file name.
Returns: a new image.
-
-
new
Magick::BinMagick::Image.new(magick_image) -> image
Creates a new Magick::BinMagick::Image instance from a Magick::Image object. The source Magick::Image object should not be a destroyed image, otherwise the Magick::BinMagickError::DestroyedImageError exception is raised.
Arguments:
-
magick_image
A Magick::Image object.
Returns: a new image.
Raises: Magick::BinMagickError::DestroyedImageError.
-
-
binary?
img.binary? -> boolean
Checks if the image consists of pixels that can have one of exactly two colors: black or white.
Returns: a boolean value.
-
black_px?
img.black_px? -> boolean
Checks if the image has at least one black pixel.
Returns: a boolean value.
-
crop_border
img.crop_border -> image
Crop border around the image. If the image can't be cropped (e.g. it has only pixels of the same color): returns an unedited copy of the target image.
Methods calculates a bounding box value for the target image (see Magick::Image#bounding_box), and uses that value to crop a copy of the target image.
Works best with binary images. For color images you might want to use the crop_border_clr version of the method.
Returns: a new image.
-
crop_border!
img.crop_border! -> self
In-place form of crop_border.
Returns: self.
-
crop_border_clr
img.crop_border_clr(n_gray_colors = 64, quantize_dither = Magick::NoDitherMethod, threshold_map = "checks") -> image
Same as crop_border, but treats a color image like it is already a binary one. The bounding box value is being calculated for a binary version of the target image, then a copy of the target image is being cropped used that value.
The method does not convert the target image to a binary, but uses a binary version only to calculate the bounding box value. For that purpose it accepts and utilizes all to_binary arguments.
Arguments: see to_binary arguments description.
Returns: a new image.
-
crop_border_clr!
img.crop_border_clr!(n_gray_colors = 64, quantize_dither = Magick::NoDitherMethod, threshold_map = "checks") -> self
In-place form of crop_border_clr.
Returns: self.
-
extent!
img.extent!(width, height, x = 0, y = 0) -> self
In-place form of Magick::Image#extent.
If width or height is greater than the target image's width or height, extends the width and height of the target image to the specified values. The new pixels are set to the background color. If width or height is less than the target image's width or height, crops the target image.
Arguments:
- width
The width of the new image.
- height
The height of the new image.
- x, y
The upper-left corner of the new image is positioned at -x, -y.
Returns: self.
-
fit_to_size
img.fit_to_size(max_width, max_height) -> image
Scales down the image to fit within the specified dimensions while retaining the original aspect ratio, but only if the image is larger than provided max_width, max_height dimensions.
Arguments:
-
max_width, max_height
Maximum allowed image dimension.
Returns: a new image.
-
-
fit_to_size!
img.fit_to_size(max_width, max_height) -> self
In-place form of fit_to_size.
Returns: self.
-
level!
img.level!(black_point = 0.0, white_point = Magick::QuantumRange, gamma = 1.0) -> self
In-place form of Magick::Image#level2.
Adjusts the levels of an image by scaling the colors falling between specified white and black points to the full available quantum range.
Arguments:
-
black_point
A black point level in the range 0..QuantumRange. The default is 0.0.
-
white_point
A white point level in the range 0..QuantumRange. The default is QuantumRange.
-
gamma
A gamma correction in the range 0.0..10.0 The default is 1.0.
Returns: self.
-
-
ordered_dither!
img.ordered_dither!(threshold_map = "checks") -> self
In-place form of Magick::Image#ordered_dither.
Note: the default value of the threshold_map option is "checks" rather than "2x2" used in the Magick::Image#ordered_dither method.
Arguments:
-
threshold_map
A dither pattern to use. Available options depend on the used ImageMagick implementation. To print a complete list of the thresholds that have been defined, run the ImageMagick with the
-list threshold
option.Some common options (from the ImageMagick documentation):
threshold 1x1 Threshold 1x1 (non-dither) checks 2x1 Checkerboard 2x1 (dither) o2x2 2x2 Ordered 2x2 (dispersed) o3x3 3x3 Ordered 3x3 (dispersed) o4x4 4x4 Ordered 4x4 (dispersed) o8x8 8x8 Ordered 8x8 (dispersed) h4x4a 4x1 Halftone 4x4 (angled) h6x6a 6x1 Halftone 6x6 (angled) h8x8a 8x1 Halftone 8x8 (angled) h4x4o Halftone 4x4 (orthogonal) h6x6o Halftone 6x6 (orthogonal) h8x8o Halftone 8x8 (orthogonal) h16x16o Halftone 16x16 (orthogonal) c5x5b c5x5 Circles 5x5 (black) c5x5w Circles 5x5 (white) c6x6b c6x6 Circles 6x6 (black) c6x6w Circles 6x6 (white) c7x7b c7x7 Circles 7x7 (black) c7x7w Circles 7x7 (white)
Returns: self.
-
-
oversize?
img.oversize?(max_width, max_height) -> boolean
Checks if the target image dimensions exceed provided height or width.
Returns: a boolean value.
-
quantize!
img.quantize!(number_colors = 64, colorspace = Magick::GRAYColorspace, dither = Magick::NoDitherMethod, tree_depth = 0, measure_error = false) -> self
In-place form of Magick::Image#quantize.
Notes:
-
the default value of the number_colors option is 64 rather than 256 used in the Magick::Image#quantize method;
-
the default value of the colorspace option is Magick::GRAYColorspace rather than Magick::RGBColorspace used in the Magick::Image#quantize method;
-
the default value of the dither option is Magick::NoDitherMethod rather than Magick::RiemersmaDitherMethod used in the Magick::Image#quantize method;
Arguments:
-
number_colors
The maximum number of colors in the result image.
-
colorspace
The colorspace to quantize in.
-
dither
Error diffusion dither that will be applied on the color reduction. A Magick::DitherMethod value.
-
tree_depth
The tree depth to use while quantizing
-
measure_error
Set to true to calculate quantization errors when quantizing the image.
Returns: self.
-
-
to_binary
img.to_binary(n_gray_colors = 64, quantize_dither = Magick::NoDitherMethod, threshold_map = "checks") -> image
Converts a color image to a binary (monochrome) image.
Combines two RMagick methods:
-
Magick::Image#quantize (color reducing step);
-
Magick::Image#ordered_dither (ordered dither filter).
The first step converts image to a grayscale format with limited number of gray tones (specified by the n_gray_colors option). The second step applies the ordered dither filter to the grayscale image, resulting a binary image.
Arguments:
-
n_gray_colors
Maximum number of gray tones in the quantized image.
-
quantize_dither
Error diffusion dither that will be applied on the color reduction step. A Magick::DitherMethod value.
-
threshold_map
A dither pattern to use.
Returns: a new image.
-
-
to_binary!
img.to_binary!(n_gray_colors = 64, quantize_dither = Magick::NoDitherMethod, threshold_map = "checks") -> self
The in-place form of to_binary!.
Returns: self.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and the created tag, and push the .gem
file to rubygems.org.
You can also run bin/console
for an interactive prompt that will allow you to experiment.
Bug reports and pull requests are welcome on GitHub at https://github.com/8bit-mate/bin_magick.rb.
Test images were generated with the https://make.girls.moe/ project.
The gem is available as open source under the terms of the MIT License.