4

I'm failing at translating the following PHP/ImageMagick code into Ruby RMagick (to make it more manageable for future users and to understand what it's really doing):

$output = array();
$returnValue = 0;
$pngFiles = $myDir->find("/.png$/i");
foreach($pngFiles as $pngFile) {
   $cmd = 'convert '.$pngFile->path.' -resize 1x1 -alpha on -channel o -format "%[fx:u.a]" info:'
   exec($cmd, $output, $returnValue);
   if($output[0] != 1) {
      logMessage("PNG file contains some alpha transparency and will not be modified");
   }
}

By now I thought I more or less understood what the convert-command is doing, but translating it to RMagick makes me rethink that.

For example: Why is $output[0] != 1 sometimes true on PNGs in $myDir, but RMagick's Image.alpha? is always true on PNGs in $myDir? Am I missing something?

I think the best way to get me back on track would be, if anyone could explain to me what the convert-command is exactly doing (including the expression %[fx:u.a]).

Update: In the meantime I've written the script I needed this information for. You can check it out at Github if it's to any help to you.

Community
  • 1
  • 1
Javier
  • 2,491
  • 4
  • 36
  • 57
  • 1
    I think - Image.alpha is probably checking to see if the image has an alpha layer, which PNGs do. Whereas that is checking a single pixel for it's transparency level. See my answer below. – Orbling Nov 20 '10 at 19:25

5 Answers5

5

The code checks to see if a particular image contains transparency.

-format '%[fx:u.a]' info:

This instructs image magick to check the first image u, the alpha channel of that a and output info on it, it will return 0 if the top-left pixel is transparent and non-zero if not I think. That is why the image is being resized to 1x1, so that only a single pixel needs to be consulted. The -channel o is the opacity channel.

So the code in English would read, cycle through all PNG files, look at the alpha channel (opacity) only, resize to a single pixel and see if it's transparent. Hence the echo message.

Unfortunately I do not know Ruby, or RMagick, but a quick look at the API seems to suggest using image.channel(AlphaChannel) to get the alpha channel (AlphaChannel is a ChannelType value, not sure if you have to specify ChannelType.AlphaChannel), then follow with .resize(1,1) to get the size down, and finish with either .pixel_color(0,0) or .get_pixels(0,0,1,1) to get the Pixel object back (get_pixels() returns an array), which I believe has an opacity attribute. However, the channel() command changes the RGB values to the value of the channel selected, and I'm not sure it preserves the opacity channel so you might just need to look at red forinstance, or omit the .channel() call entirely - though I do not know if that would disrupt the result offhand.

Perhaps if Ruby supports decent functional programming approaches.

image.channel(AlphaChannel).resize(1,1).pixel_color(0,0).red

or this if pixel_color() does not return the opacity for some reason

image.channel(AlphaChannel).resize(1,1).get_pixels(0,0,1,1)[0].red

Without the channel() calls it would be:

image.resize(1,1).pixel_color(0,0).opacity

or

image.resize(1,1).get_pixels(0,0,1,1)[0].opacity

Again, my Ruby is non-existent, so you may have to rearrange those a lot, but the primitives are there.

References

  1. RMagick Documentation
  2. ImageMagick 'fx' escapes
  3. ImageMagick -channel options
Orbling
  • 20,413
  • 3
  • 53
  • 64
1

Posting this for anyone who is still looking for a solution to this, there is a way of doing this in ruby using the rmagick gem described here https://stackoverflow.com/a/41282162/1975112

Community
  • 1
  • 1
0

The php code you show (which really just sends the work to convert in a shell) does not check to see if the images have alpha channels, it just takes whatever file is given and turns it on. If it already had one there would be no file change, but convert is not being asked to make any decision based on the status, just go ahead and add the channel.

Caleb
  • 5,084
  • 1
  • 46
  • 65
  • Sorry, I forgot the add the whole PHP code. Please check my edited question. If the convert-command doesn't check for existing alpha-values, why is the convert-return-value checked and interpreted as such? – Javier Nov 10 '10 at 12:50
0

why did you not copy just the command and call it with system ?

no gems required ... no questions, code should look almost the same.

EDIT: RMagic only wraps imagemagic so why to bother with rmagic if you already have imagmagic command string.

mpapis
  • 52,729
  • 14
  • 121
  • 158
  • 2
    I just edited my question, hope my problem is a bit clearer now. As long as I don't understand what the convert-command is exactly doing, it doesn't really matter if I call that stuff with system or wrap it with RMagick. I don't want to use code I don't fully understand. – Javier Nov 14 '10 at 23:49
0

I've never coded a single line of Ruby, but here is a partial remake of the PHP script:

require 'find'

pngFiles = Dir.glob("*.png")

Find.find('./') do |f|
  if system 'convert ' + f + ' -resize 1x1 -alpha on -channel o -format "%[fx:u.a]" info' do
    print "PNG file contains some alpha transparency and will not be modified"

I think that the only thing you need to check for is just an alpha channel, not all of that complicated stuff. Look at this page for more info: http://www.imagemagick.org/script/escape.php. It has a %A operator, and that outputs something about the alpha channel.

Blender
  • 289,723
  • 53
  • 439
  • 496
  • Thank you, but this doesn't really answer my question. I'm not trying to refactor the PHP script and I still don't know what the convert command is doing exactly. All the "complicated stuff" is already implemented this way in a working PHP script. – Javier Nov 19 '10 at 11:00