forthebadge forthebadge Gem Version

This gem was last updated on the 18.11.2023 (dd.mm.yyyy notation), at 08:22:30 o'clock.

(This image was partially autogenerated via cfdg. You can re-use this image and modify it if you wish to without restrictions. For the actual .cfdg code, please have a look at the gallery there: https://www.contextfreeart.org/gallery/)

How to install this project

The obvious way is to do this:

gem install image_paradise

However had, installing into the user directory may be more useful, depending on your use case:

gem install image_paradise --user-install

The latter may be a bit better, as it should be easier to get this installed into the home directory.

Then you can symlink bin/image_paradise to $PATH or any other name as-is. Or just start irb, require 'image_paradise', and call whatever class you need there. You could even do so for the ruby-gtk3 bindings, if you have these installed, and the gtk_paradise gem.

Example for this:

require 'image_paradise'
ImageParadise.confree_GUI # Start the gtk-confree GUI.

For an explanation of the --user-install option see the article here:

https://guides.rubygems.org/faqs/#i-installed-gems-with---user-install-and-their-commands-are-not-available

Flip-flopping an image from left-to-right

If you want to flip an image left-to-right, you can use the method .flip_image_left_right. The file resides at image_paradise/toplevel_methods/flip_image_left_right.rb.

Example:

require 'image_paradise/toplevel_methods/flip_image_left_right.rb'
ImageParadise.flip_image_left_right() # Pass the file path to this method.

Transparent images

You can use this API to make an image transparent:

require 'image_paradise/toplevel_methods/make_this_image_transparent.rb'
ImageParadise.make_this_image_transparent
ImageParadise.make_this_image_transparent('foobar.jpg')

This will try to make use of ImageMagick's convert ability.

Negating an image

You can negate an image, aka the "flipped" colour state, via:

require 'image_paradise/toplevel_methods/negate.rb'
ImageParadise.negate()
ImageParadise.negate('filename_here.jpg')

If you negate such an image again, you will have the original image back.

Merging image files together

You can use the toplevel method ImageParadise.merge_these_images in order to merge several image files together. This depends on the binary called convert, from ImageMagick. Note that this will merge from the left-to-the-right side, and use white background by default if an image has to be padded. The biggest image will determine the amount that has to be padded here.

As first argument simply pass an Array of the files that you wish to merge, such as:

ImageParadise.merge_these_images(%w( foo.png bar.png bla.png ))
ImageParadise.merge(%w( foo.png bar.png bla.png )) # <- This also works.

Greyscaling images

You can grayscale images via:

ImageParadise.greyscale_this_image()
ImageParadise.grayscale_this_image()

This currently (Jan 2019) depends on the gem called mini_magick. In the future we may add some more flexibility to this method, but for the time being mini_magick is a dependency if you wish to make use of these toplevel methods.

Greyscaling an image may be useful if you wish to use this for optical character recognition, aka recognising written text on it.

class ImageParadiseImageToAscii

This class can convert images to ASCII files, if ImageMagick (and the rmagick bindings) are available.

To specifically require this class, do this:

require 'image_paradise/requires/require_image_to_ascii.rb'

Then pass the filename into the class:

result = ImageParadise::ImageToAscii['foobar.jpg']
result = ImageParadise.image_to_ascii('foobar.jpg')

or

_ = ImageParadise::ImageToAscii.new '/foo/bar.png'
_.to_ascii # Generate the ascii "image" here specifically, via this method call.

or

  print ImageParadise::ImageToAscii('yo.png').to_ascii(width: 50)

  +--------------------------------------------------+
  |oooooooooooooooooooooooooooooooooooooooooooooooooo|
  |oooooooooooooooooooooooooooooooooooooooooooooooooo|
  |oooooooooooooooooooooooooooooooooooooooooooooooooo|
  |oooooooooooooooooo===++++====ooooooooooooooooooooo|
  |ooooooooooooo=+:~.~........~~~:+=ooooooooooooooooo|
  |oooooooooo==:~...~~:++++++:~~..~~:+=oooooooooooooo|
  |oooooooo=+:...~++====oooo====+:~..~:+=oooooooooooo|
  |ooooooo=+~..~:++==ooooooooooo=++:~..~+=ooooooooooo|
  |oooooo=+~.~:+=+~.~~~~~~~~:~~~.~:++:~.~+=oooooooooo|
  |ooooo=+~~.+===~................~+==:.~~+=ooooooooo|
  |ooooo=:~~:+=+:~................~~+=+:~.:=ooooooooo|
  |ooooo=~.~+==+~.......XXXXX.......+==+~.:=ooooooooo|
  |ooooo=~~~+==:~.......XXXXX.......:==+~.:=ooooooooo|
  |ooooo=~~~:==+~.......XXXXX......~+==+~.~=ooooooooo|
  |ooooo=:~~~+=++~.................:+=+~~~:=ooooooooo|
  |ooooo=+:..~+==+~~...........~~~+==+~..:+=ooooooooo|
  |ooooooo+:..~:+=o=+:........:+====:~.~:==oooooooooo|
  |oooooooo=+~.~~:+==+~......~+==+:~..~:+oooooooooooo|
  |ooooooooo=+:~..~~:~~.......~:~~..~:+oooooooooooooo|
  |oooooooooooo=+~~..............~:+=oooooooooooooooo|
  |ooooooooooooooo==++:~~~~~~:++==ooooooooooooooooooo|
  |oooooooooooooooooooooooooooooooooooooooooooooooooo|
  |oooooooooooooooooooooooooooooooooooooooooooooooooo|
  |oooooooooooooooooooooooooooooooooooooooooooooooooo|
  +--------------------------------------------------+

Add colours via the "colour" option

  require 'image_paradise'
a = ImageParadise::ImageToAscii.new "http://www.evangogh.org/images/paintings/self-portrait.jpg"
puts a.to_ascii(color: true)

Command Line examples:

image_to_ascii ~/Desktop/foo.png # Local file.
image_to_ascii http://www.google.com/images/foo.png # Remote image.
image_to_ascii -c -f html ~/foobar.jpg > ~/Desktop/ascii-as-html.html # Output via HTML.
image_to_ascii -w 50 -c -f html ~/foo/bar.jpg > ~/Desktop/saturdaynight.html # Or smaller.

To display help:

  image_to_ascii -h

  Usage: image_to_ascii [options] <path_or_url>
    -w, --width WIDTH                Width of the finished Ascii Image (Default: 150)
    -f, --format [text/html]         output format (Default: text)
    -c, --color                      Switch to use colored terminal output (Default: false)
    -i, --invert-chars               Invert the character map. *Depending on background and image color - this can make the result clearer.*
    -v, --version                    Show the version of this project
    -h, --help                       Show this message

SVG

ImageParadise now has a submodule called Svg, for svg-related objects. Documentation is currently missing for this part. Hopefully I will have more time in the future to add the missing documentation here. :\

ImageMagick versus GraphicsMagick

GraphicsMagick is a fork of ImageMagick, started in the year 2002.

I do not know the real differences between these two projects. For now, the image_paradise gem will focus on ImageMagick first. Perhaps at a later time I may add support for GraphicsMagick, but I want to finish the GUI components first, before looking for more flexibility after that.

Create background images and wallpapers

To create a white wallpaper, use this API:

ImageParadise.white_wallpaper
ImageParadise.white_wallpaper(width = :default, height = :default)
ImageParadise.white_wallpaper(1200, 800)

This makes use of a more general API called:

ImageParadise.wallpaper()

The first argument is the colour for that background image. The default colour here will be black, hence a black background image.

cfdg

The image_paradise gem includes code that allows the user to batch-generate images from .cfdg files, making use of the cfdg binary (context free design).

You can download cfdg from:

https://www.contextfreeart.org/downloads.html

I typically compile the variant from source directly.

My long-term goal in this regard, as far as the image_paradise gem is concerned, is to use a commandline variant, as well as a GUI wrapper for this. The GUI will be written in ruby-gtk3. Perhaps www-bindings via sinatra may also be offered one day, via the ImageParadise project - let's see.

Additionally, the image_paradise .gem will include many .cfdg example files, written by many different people (mostly; I wrote a few .cfdg files as well but not many). The filename of all these .cfdg files must be downcased - I mention this because some of the upstream .cfdg files have upcased characters, which annoys me. Keep it simple, folks!

Some of these files are +16 years old and have to be updated really, but you know how it is when time is a limited resource. So the rules that govern some of these .cfdg files is ... a bit outdated.

I'll also have to add URLs to some of these ancient .cfdg files, author-information and so forth; this is low priority for now, though. It's mostly clean up work, which isn't as much fun to do. :-)

To start the ruby-gtk3 bindings, depending on the gtk_paradise gem, you can try this from the commandline:

confree_generator --gui

The following image shows how this may look in December 2021 - in the long run I intend to improve this GUI, but for now the most important part is to finish the desired functionality. I'd love to have a full editor for CFDG one day:

Todo list for the ruby-gtk3 wrapper:

  • On middle-mouse scroll-wheel scroll-event, change the number of the gtk-entry there, e. g. upwards scrolling means larger width, down-scroll means smaller width respectively.

Existing features and functionality for the ruby-gtk3 wrapper over the cfdg binary:

  • Show all existing local .cfdg files via a button that can be clicked. Upon clicking that button, the file is loaded, and then a new image is created from this via cfdg. This has been implemented in March 2021.

  • Upload to imgur via an image-event-button (the old upload-to-imageshack is no longer available, but perhaps it may be re-added in the future)

In September 2022 the widget was rewritten and looks a bit better now:

As for .cfdg files distributed as part of the image_paradise gem, I try to adhere to this specification in the long run:

  • The file name should be noted near the very top of the file.
  • All .cfdg file names must be lowercased at all times, so no files called foo_BAR.cfdg.
  • If they were obtained from the www, a hyperlink should exist within the file, pointing to that original .cfdg file. In this case the author should be mentioned as well, and the creation date and addition date added too.

ImageParadise::Identify

If you need meta-data about an image then class ImageParadise::Identify may be of help. Internally it is just a wrapper over ImageMagick's identify functionality, but the key idea is to provide an OOP query to these features (when they seem relevant), and use that abstraction for other classes to make use of.

This class has to remain flexible, because I intend to keep it as a base-class for whenever I need information about an image programmatically.

cfdg cheat sheet

I am forgetting specifications used in cfdg, and I can not always find them when I want to look them up. So I decided to also add a few hints here; mostly for my own use case, but perhaps it may also help other folks learn cfdg more quickly.

# Transparent background:
background { a -1 }

# Rotate a shape:
r 5 # rotate by +5 %

Adding a comment to an image file, via metadata

ImageMagick allows you to add a comment to an image file.

The ImageParadise gem added support for this as well, just as a wrapper over Imagemagick.

API use:

ImageParadise.add_this_comment_to_that_image()
ImageParadise.add_this_comment_to_that_image('This is the comment')
ImageParadise.add_this_comment_to_that_image('This is the comment','existing_file.png')

ImageMagick tricks

This subsection just is a little random trick-collection.

To decrypt a .pdf document and extract the images, use the authenticate command-line option:

convert -authenticate password input.pdf output%d.png

Morphing two images together

You can morph two images together via ImageMagick.

ImageParadise makes this available via this API:

ImageParadise.morph_these_images
ImageParadise.morph_these_images('foo.png','bar.png')
ImageParadise.morph_these_images('foo.png','bar.png','output_file.png)

Pass in the two images; the third argument may be the filename that you wish to use for the output-file.

Graphical User Interface for the ImageParadise project (GUI)

Since as of February 2021 I am slowly working on a set of ruby-gtk3 code that integrates the functionality detailed above. Note that I will only add support in the GUI if I also have documented - or will document - the commandline behaviour shown above. The reason as to why is that I want to sync commandline and GUI, but the commandline is the main driver, whereas the GUI is merely a reflection of the commandline tools of this project.

This should help keep things up-to-date, as more changes come at a later time. The GUI bindings will not replace something like GIMP, for instance.

The gtk-widget here will operate on images via an "image-chain". This is simply an array of images that are stored subsequently. It's not as elegant as real layers and undo-operations in, say, GIMP, but it is easy to implement and work-with. See the undo button for an example of this.

To start the ruby-gtk3 bindings, try:

image_paradise --gui

image_paradise --gtk  # or this variant
image_paradise --gtk3 # or this variant; this will start the gtk-cfdg widget actually
image_paradise --gtk-image # or this variant

Note that in February 2022 the ruby-gtk2 bindings of the gkt-image widget were removed. Perhaps at a later time they may be re-added, but for the time being I focus solely on ruby-gtk3 instead.

Which features are available?

Well, as explained above, only features are made available via the GUI that are documented here on this page.

So far the following features have been implemented via the ruby-gtk3 bindings and ImageMagick (March 2021):

  • Flip horizontally
  • Greyscale the image
  • Add a coloured border around an image
  • Negate the image (180° colour-flip)
  • Resize the image
  • Apply a gaussian blur onto the image
  • Add a roundish-circle as the main center view onto the main image
  • Draw text onto the image (currently limited, only one font; will have to add support for more fonts there)
  • Basic shape drawing: drawing a line is possible. Drawing a rectangle is possible.
  • Crop the image (currently only via gtk-entries, but one day we should be able to overlay a crop-mask to calculate the crop area properly)
  • Upon pressing the middle-mouse-button on the gtk-entry displaying the colour in use for the border, randomly assign a new colour from the available HTML colours
  • Able to create a new image (currently background is white)

Todo List:

  • The drawing lines and rectangle should occur on a new image, rather than this creates a new image as it currently does.
  • Show info-box displaying information about the current image, ideally on the right-hand side. This should include size, and perhaps additional information about the image-type as well, alpha value and so forth. This has been partially added; needs more information still and be made prettier as well.
  • Provide an "undo" button (can be lazy, aka store incomplete images)
  • Add a file-open button. Probably place it on the right side somewhere.
  • Add colour-gradients.
  • Add filters.
  • Add de-novo creation of images; possibly via a small widget that allows us to do so. That could be a separate widget that can then be integrated into the parent widget.

  • Add way to query the x and y position accurately on a mouse-button event, for the main image.

  • Add a resizable pane widget to the bottom area of the main image so that the user can change the size.

  • Basic shape drawing: we need to be able to combine it into the currently loading image, aka "draw on screen" as-is.

  • Upon mouse-scroll-wheel press-events on the entry with the percentage value, change accordingly up or down, so that the user may just use the mouse for changes.

  • Basic shape drawing: we need to add the remaining functionality such as drawing a circle, a line and what not.

  • Add a direct way for the user to do a resize operation. Perhaps a general input-entry that gets highlighted or something. The idea is to support this:

    convert -resize 42x148 input.jpg output.jpg

But to not have the user enter the output name (or perhaps still do hmm).

  • Add a way to specify which lines are to be drawn via a script. That way we can use it to automatically draw or re-draw specific images as-is. The idea would be that we could programmatically generate any image possible, but this will probably require changes to the commandline version first, before expanding this onto the GUI.

Blur effects via ImageParadise.blur()

You can use the following API for blur-effects:

ImageParadise.blur
ImageParadise.blur('foo.png')
ImageParadise.blur('foo.png', 5)
ImageParadise.blur('foo.png', 50)

These will modify an image, aka blur it. The second argument is the radius for the blur operation to use. This functionality depends on ImageMagick being installed on the host computer system in use.

Changing the quality of an image

Via ImageMagick you can use this command to change the quality of an image:

convert -quality 10% input.jpg output.jpg

Via ruby and the image_paradise project, you can use this API:

ImageParadise.quality('input.jpg',10,'output.jpg'

Be careful when you have .jpg files; from experience I see a lot of deterioration in regards to quality if you have to do many operations again and again. In this case, you may be better off converting into .png, then modifying the .png, before then converting it back into .jpg again. Note that this also causes loss in quality usually, but you have only two conversion steps, whereas if you, say, have to do 10 operations on the .jpg, drawing stuff on the canvas, this may lead to worse image quality if you started with a .jpg file and keep on working with it.

Even a one-time saving to .jpg may impact its quality negatively, depending on the chosen quality. As a rule of thumb, if I want to maintain some useful quality in a given image, I don't go below the 84% quality threshold for .jpg files. In the long run, though, I will probably switch to a better format when it comes to lossy encoding, perhaps WebP - we'll see.

Rotating an image

(Technically this is similar to flip-flop, but I added this functionality at a later point, so the flip-flop subsection here shall remain for the time being.)

The commandline API for rotating an image called FOOBAR.png, in regards to image_paradise, may go so:

imgparadise FOOBAR.png --rotate=33%
imgparadise foo.png --rotate=90%
imgparadise *.png --rotate=90%

Simply pass the rotation-value that you wish to use into --rotate.

Be careful, though - this command will overwrite the image, so make sure to backup your old image before applying this command.

Sometimes you may dislike the background colour used, after having applied a rotate-effect. In this case, recall that you can specify the background color via -background red or another name. (This may be integrated into the ruby-gtk3 wrapper, but it is currently, in May 2021, not added.)

The difference between the fill colour and the stroke colour

Fill colour:

  • It fills objects with that colour. So a fill colour of red, will paint the object's content, such as a circle in red too. You thus get a red circle.

Stroke colour:

  • This colour draws the outline of an object. In other words, it will specify a border.

Table of some ImageMagick commands

I did not want to google all the time, so here is just a short memo for me which options exist in ImageMagick. This is currently very incomplete; in the future I may extend this list.

-pointsize 24        # specify the width of the drawling
-stroke red          # use red as the colour for the paint-stroke to be done
-fill red            # this is the fill colour, aka the content of an object
-strokewidth 3       # set the width, in px, of the paint-stroke action
-linewidth 5         # the width of the line, when drawing a line
-font Arbuckle.ttf   # use this font; you can specify a local file path too, to a .ttf file
-annotate 45x0+10+30 # Annotate via 45° angle

Because I may re-use the -font option in particular, here is a variant that I use:

convert -pointsize 24 -font /home/x/src/fonts/Hack-Regular.ttf -stroke red -fill red -annotate 0x0+10+30 testing.com /Depot/NJOY/WaterGirl.png output.png

ImageMagick itself supports at the very least TrueType fonts, PostScript and OPTION1 fonts.

Borders

This subsection explains some general stuff about borders. In this context a border means an area around an image, such as a black border around an image that has a width of 3 pixels (px).

You can add some borders to images thanks to ImageMagick. The image_paradise gem supports this as well, to some extent.

The toplevel method ImageParadise.add_black_border_to_this_image() can be used to add a black border to an image. It is a very simple method. The first argument to this method is the path to the image at hand. The second argument specifies the size of the border, in pixels. So, if you pass the number 3 as second argument then this would mean to draw a border 3 pixel wide around the image at hand.

Invocation example for the local image file called foobar.png follows next - adapt this to your own needs as-is:

require 'image_paradise/toplevel_methods/add_black_border_to_this_image.rb'
ImageParadise.add_black_border_to_this_image('foobar.png', 3) # we want the border to have 3 pixels

Obviously for this to work, the file must exist locally.

It is also possible to add a rounded black border. This can be seen in traditional card games, such as magic the gathering.

If you want to use that, consider making use of the following class/file and API:

require 'image_paradise/utility_scripts/magic_card_border.rb'
ImageParadise.:MagicCardBorder.new(ARGV)
# such as in:
# ImageParadise.:MagicCardBorder.new('foobar.png')

See the --help options for what the class will support.

You can alias it to e. g. magic-rounded and then invoke it via:

magic-rounded --size=5
magic-rounded --size=5 foobar.png
magic-rounded --size=12 foobar.png
magic-rounded --size=25 foobar.png

The --size parameter determines which size to use, via the commandline. I recommend keeping the --size parameter fairly small; more than --size=12 is rarely necessary, in my opinion. Better to have a slight black border than a huge one - but, either way, this is entirely up to the user.

Some toplevel methods explained

The method ImageParadise.default_colour? will give back the default colour for the project, if it has been assigned. I needed this because some image-related operations require a colour, and being able to omit this for subsequent use can be convenient, aka set the colour once, and then continue to work from there.

API consideration

This subsection shows a few syntax examples how I plan to rewrite the project in 2022.

Write the text "Hello world" on the image FOOBAR.png:

textonimage FOOBAR.png --text="Hello world" --colour=darkgreen --font-size=22 --position=3,4

This will be passed to class ImageParadise::TextOnImage, where ipa is an alias I use towards bin/image_paradise. I intend to improve this class over the coming weeks.

An even simpler variant follows for a closely related script, at bin/img_text:

imgtext what the heck some_file.png --darkblue
imgtext what the heck some_file.png --tomato # you can pass HTML colours here

Why is the example shown above via imgtext nice to have?

Well - the idea here is that you first think what kind of text you want to display on the image. Then, you pass the image filename, such as foobar.png. And then you append extra commandline flags via -- such as --darkblue.

It may be hard to explain why this is useful, but just give it a try on some existing image, and play around a bit with it. Further options to customise this even more may be added in the future.

Which fonts are available for ImageMagick?

The answer to this question depends on your computer system.

If you are, however had, like me and often forget then the following list will contain some font names that may be available on your linux system too. On Windows I do not know whether these are available or not, but since Linux is my main operating system I focus primarily on Linux.

The following list is not complete - it just gives a few helpful pointers to available names that may be usable by you.

Here we go:

AvantGarde, Bookman, Courier, Helvetica, NewCenturySchlbk,
Palatino, Symbol, Times, Bitstream-Charter, Century-Schoolbook,
Chandas, Courier, DejaVu-Sans, DejaVu-Serif, Garuda, Hack-Regular,
Kedage-Normal, Kinnari, Liberation-Mono, Liberation-Sans,
Liberation-Serif, Loma, Luxi-Mono, Luxi-Sans, Luxi-Serif,
Mallige-Normal, Nimbus-Mono-L, Nimbus-Roman-No9-L,
Nimbus-Sans-L, NimbusMonoPS-Regular, NimbusSans-Bold,
Norasi-Bold, Noto-Mono, Noto-Serif-Bold, Oxygen-Mono,
Terminus-Regular, Umpush, URW-Gothic-L-Book, Utopia.

Embedding the filename into an image file

You can embed the filename (or any other text) into images via imagemagick. In April 2022, I had a use case where I needed to put down the name of the image file into the image itself.

The syntax from the commandline looks as follows:

convert name_of_the_image_file_goes_here.jpg -font Luxi-Mono -pointsize 32 -draw "gravity northwest fill white text 0,15 'Filename' " output.jpg
convert TANA* -font Luxi-Mono -pointsize 32 -draw "gravity northwest fill white text 0,15 'Filename' " output.jpg

I wanted to automate this, though, so the following API was added to the ImageParadise gem:

ImageParadise.embed_the_filename_into_this_image()
ImageParadise.embed_the_filename_into_this_image('name_of_the_image_file_goes_here.jpg')

This is not very customizable though as I just use it for hardcoded values mostly. You may have to adjust it to your own use case; at the least the method exists, so you can modify it as-is. The second argument is a Hash which allows for some modifications.

For instance, a larger text size can be done via:

ImageParadise.embed_the_filename_into_this_image('foobar.jpg', { font_size: 50 })

To combine this with a different colour use:

ImageParadise.embed_the_filename_into_this_image('foobar.jpg', { font_size: 50, colour_to_use: :tomato }) # You can use the HTML colours here.

Note that you can also pass a directory as the first argument. So, rather than pass 'foobar.jpg', you could pass '/foo/bar/' and the method will gather all .gif, .jpg and .png files there, then work on these one after the other. This allows us to batch-process whole directories containing images. Don't forget to keep a backup of these images before calling this method, though!

Usage example:

ImageParadise.embed_the_filename_into_this_image('/foo/bar/')

Determining whether a given file is an animated image

The following functionality depends on ImageMagick.

To determine whether an image is animated you can use the following API:

ImageParadise.is_this_image_animated?('/foobar.gif') # => true
ImageParadise.is_this_image_animated?("TANAKA.jpg")  # => false

Determining whether a given file is an image file or whether it is not

You can use the following API to determine whether the given file is an image file or whether it is not.

ImageParadise.is_an_image_file?()
ImageParadise.is_an_image?()

Both variants work fine. The second is a bit shorter, so let's look at a specific example:

ImageParadise.is_an_image?('/tmp/cat.png')
ImageParadise.is_an_image?('/tmp/dog.gif')
ImageParadise.is_an_image?('/tmp/deer.bmp')

This will return true if it is an image, and false otherwise. Presently (in 2022) this works via a constant where the file types are registered, e. g. ".png" or ".jpg" all are files. In the future another method may be added that uses either "file" to identify the file at hand, or another variant by probing the content to determine whether this is really a file or not. But currently no such API exists. If it will be added then it will probably have another name, so for the time being ImageParadise.is_an_image?() should suffice.

Support for chunky_png and examples using chunky_png

ChunkyPNG is a ruby-only library that helps the user create .png files or read from existing .png files. It is super-convenient to use, in many ways even easier to use than ImageMagick. On the other hand, a lot of the functionality that ChunkPNG offers can be used via ImageMagick. So perhaps ImageMagick is better.

Still - as ChunkyPNG exists, I decided to add support to it within the namespace called ImageParadise::ChunkyPNG. This may be a bit hackish, and support will not be complete, but just more of an example what can be done via ChunkyPNG.

This subsection will list some examples.

To combine two .png files, and overlay one onto the other, use:

ImageParadise::ChunkyPNG.overlay('Leeann_Tweeden.png','Cute_Biker.png', :center)

Support via Pango

ImageMagick knows how to use Pango.

Consider the following commandline examples:

convert -size 600x100 -gravity center -pointsize 48  pango:"The <span foreground='blue'>blue</span> word." output.png
convert -size 400x200 -gravity center -background khaki -pointsize 30 pango:"<i>A</i> &#x229B; <i>B</i> &#x21D2; <i>C</i>" chars.png
convert -size 400x200 -gravity northeast  -background khaki  -pointsize 30 pango:"<span foreground='green' size=\"55555\">A</span><span foreground='green' size=\"30000\">A</span><span size=\"30000\">B</span>C" chars.png

Resizing an image

Images (in 2D) typically have a width and a height setting, such as 400px width and 300 px height. This is typically denoted like this, via a shorthand notation: 400x300.

Naturally you may want to resize an image eventually, for instance, for displaying it on a webpage. Size often matters here, due to the data volume passed to the recipient (the visitor).

ImageMagick allows you to resize an image, via the following commandline invocation:

convert -resize 40% foobar.jpg output.jpg

This worked if you then use identify to check the width and height:

identify foobar.jpg

Result: foobar.jpg JPEG 280x499 280x499+0+0 8-bit sRGB 32644B 0.000u 0:00.000

identify output.jpg

Result output.jpg JPEG 112x200 112x200+0+0 8-bit sRGB 8141B 0.000u 0:00.000

So, if you multiply 280.0 * 0.4 you get 112.0, which is precisely the width value that the file output.jpg has.

I wanted an API in ruby that would allow me to do the same:

shrink foobar.jpg 40%

on the commandline. However had, I realised that I may want to omit the trailing % specifically, or even omit the last part altogether, thus only using the following commandline variant:

shrink foobar.jpg # the first argument is the locally existing file

In that case, shrink will shrink the image down to 75%, thus, width and height will be multiplied by a factor of 0.25 to obtain the new width and height (rounded down, always, to get integer pixel values).

If you want to do this from within ruby, you can, after requiring the image_paradise gem, use any of the following:

ImageParadise.resize_by_percent('foobar.jpg')
ImageParadise.resize_by_percentage('foobar.jpg')
ImageParadise.resize_percent('foobar.jpg')
ImageParadise.percent('foobar.jpg', 20)
ImageParadise.percent('foobar.jpg', '30')
ImageParadise.percent('foobar.jpg', '40%')
ImageParadise.resize('foobar.jpg', '20%')
ImageParadise.resize('foobar.jpg', '30%')
ImageParadise.resize('foobar.jpg', '40%')

Use whatever variant you prefer here. The first one is the official name; I think it is the best to remember. ImageParadise.percent() exists mostly in the event that you quickly want to use it from within irb, but you can also use the shorthand API ImageParadise.resize() - it is all up to you.

The executable that bundles this functionality into a standalone file can be found at bin/resize_by_percent.

Query the width and the height of an image

You can use the following method to determine (return) the width of an image (in n px, aka n pixels):

ImageParadise.width_of_this_image?
ImageParadise.width_of_this_image?('foobar.png')
ImageParadise.width_of_this_image? "red_six_sided_die.png"

A similar method exists for the height of an image:

ImageParadise.height_of_this_image?
ImageParadise.height_of_this_image?('foobar.png')
ImageParadise.height_of_this_image? "red_six_sided_die.png"

Compression of images in general

This subsection just very briefly mentions a few interesting knowledge bits about compressing images in general. It is just a reminder, not an extensive article entry.

Higher quality in regards to images usually means that there is less compression of the image at hand.

Photographs tend to compress better with JPEG than with PNG.

The idea in all forms of compression is to reduce or eliminate bits that do not convey their full potential information content.

ImageParadise.monochrome

The ImageParadise.monochrome() API can be used to make an image monochrome - aka only black and white.

Usage example:

x = ImageParadise.monochrome('/Depot/j/NJOY/VidaGuerra.jpg')()

ImageParadise.charcoal

Another way to get a black-white image is via ImageParadise.charcoal.

Usage example:

result = ImageParadise.charcoal('Water.jpg')
result = ImageParadise.charcoal('/Depot/j/girl.jpg')

ImageParadise.canny

First, let's look at an image to see what ImageParadise.canny() does:

The result can be seen on the right side.

To use this for your own images, use the following API:

x = ImageParadise.canny('/Depot/j/NJOY/VidaGuerra.jpg')

Venetian gradient background

First, the image:

The API to use is:

ImageParadise.create_gradient(:venetian, '500x500', 'gray50')

The second argument specifies the width x height of the image to be created anew.

Licence

The licence for this gem is the MIT licence.

Basically the most important part of the MIT licence is that, aside from you being able to use the project as you see fit, is the no warranty disclaimer to avoid any potential misuse from the use of the software at hand.

You can read up on this licence here:

https://opensource.org/licenses/MIT

The usual copyright assignment is:

Copyright 2023 Robert Heiler

Contact information and mandatory 2FA coming up in 2022

If your creative mind has ideas and specific suggestions to make this gem more useful in general, feel free to drop me an email at any time, via:

shevy@inbox.lt

Before that email I used an email account at Google gmail, but in 2021 I decided to slowly abandon gmail, for various reasons. In order to limit the explanation here, allow me to just briefly state that I do not feel as if I want to promote any Google service anymore when the user becomes the end product (such as via data collection by upstream services, including other proxy-services). My feeling is that this is a hugely flawed business model to begin with, and I no longer wish to support this in any way, even if only indirectly so, such as by using services of companies that try to promote this flawed model.

In regards to responding to emails: please keep in mind that responding may take some time, depending on the amount of work I may have at that moment. So it is not that emails are ignored; it is more that I have not (yet) found the time to read and reply. This means there may be a delay of days, weeks and in some instances also months. There is, unfortunately, not much I can do when I need to prioritise my time investment, but I try to consider all feedback as an opportunity to improve my projects nonetheless.

In 2022 rubygems.org decided to make 2FA mandatory for every gem owner eventually:

see https://blog.rubygems.org/2022/06/13/making-packages-more-secure.html

Mandatory 2FA will eventually be extended to all rubygems.org developers and maintainers. As I can not use 2FA, for reasons I will skip explaining here, this means that my projects will eventually be removed, as I no longer have any control over my projects hosted on rubygems.org (because I can not use 2FA).

At that point, I no longer have any control what is done to my projects since whoever is controlling the gems ecosystem took away our control here. I am not sure at which point ruby became corporate-controlled - that was not the case several years ago, so something has changed.

Ruby also only allows 2FA users to participate on the issue tracker these days:

https://bugs.ruby-lang.org/issues/18800

But this has been reverted some months ago, so it is no longer applicable. Suffice to say that I do not think that we should only be allowed to interact on the world wide web when some 'authority' authenticated us, such as via mandatory 2FA, so I hope this won't come back again.

Fighting spam is a noble goal, but when it also means you lock out real human people then this is definitely NOT a good situation to be had.