0

I need to change each hue of yellow to blue, and each hue of dark gray to light gray in PNG images with transparency.

The problem is:

I can't use Photoshop, because I have 100 images, and I need to change hues many time. I can't use Image Magick, because I need more sophisticated calculations, than '-fx' can do. I can't use PHP imagefrompng(), because this nasty crap not works with a lot of my images, even with all suggested fixes like:

$background = imagecolorallocate($png, 255, 255, 255);
// removing the black from the placeholder
imagecolortransparent($png, $background);
// turning off alpha blending (to ensure alpha channel information is preserved, rather than removed (blending with the rest of the image in the form of black))
imagealphablending($png, true);
// turning on alpha channel information saving (to ensure the full range of transparency is preserved)
imagesavealpha($png, true);

and so on. It works with some images, but not with others.

All I need is a PNG library (maybe not in PHP), that can give me red, green, blue and alpha component of a pixel at coordinates x, y, and then set this pixel after my calculations, eg:

$rgba = getrgba($image, $x, $y);
$rgba = my_function($rgba);
setrgba($image, $x, $y, $rgba);

Maybe you can suggest libraries in other languages, not only PHP?

Gardner
  • 9
  • 1
  • Welcome to Stack Overflow! Please read the introductory [tour] some time. Questions asking us to recommend or find a book, tool, software library, tutorial or other off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. See also the [Help]: [What topics can I ask about here?](http://stackoverflow.com/help/on-topic) – Jongware Nov 07 '16 at 11:28

2 Answers2

0

If you don't mind using Python check out Pillow, specifically its PixelAccess class. These threads (1, 2) should be helpful and have some code examples.

evpav
  • 13
  • 1
  • 5
0

Method 1

If you just want to get at the raw pixel values of R,G,B and Alpha without worrying about compression and encoding, use ImageMagick to convert your image to plain, uncompressed, unencoded binary and read it and process it to your heart's content.

So, if we make a 1x1 pixel PNG file with RGBA(0,64,255,0.5) to test with:

convert -size 1x1 xc:"rgba(0,64,255,0.5)" a.png

Now we can get ImageMagick to make a raw, RGBA file that you can read and process as you wish with whatever language you wish at whatever level of complexity that you wish:

convert a.png rgba:data.bin

and now we can look in that file:

xxd data.bin

Result

0000000: 0040 ff80                                .@..

There you can see and read all the RGBA pixels. When you are finished, just do the opposite to get back a PNG - note that you must tell ImageMagick the size first since it cannot know this:

convert -size 1x1 rgba:data.bin new.png

Note that ImageMagick is quite a large package to install, and you can achieve much the same as the above with the much lighter-weight vips package:

vips VipsForeignSaveRaw a.png data.rgb

Method 2

Alternatively, if you want your data as uncompressed, human-readable ASCII, use the venerable NetPBM formats of PPM (Portable Pixmap) and PGM (Portable Greymap) - see NetPBM on Wikipedia.

Make a 4x1 image and write as PPM:

convert -size 4x1 xc:"rgba(0,64,255,0.1)" -compress none ppm:-
P3
4 1
65535
0 16448 65535 0 16448 65535 0 16448 65535 0 16448 65535

You can see the 4 repeated RGB values there hopefully. If you want it as a file, just change the ppm:- at the end with someFile.ppm.

Make same image again and extract Alpha channel to separate file:

convert -size 4x1 xc:"rgba(0,64,255,0.1)" -alpha extract -compress none pgm:-
P2
4 1
65535
6554 6554 6554 6554 

Hopefully you can see that 6554 is 0.1 on a scale of 0-65535.

If you just want 8-bit data on any of the above, add in -depth 8.

Method 3

As Glenn suggests in the comments, another option is to omit the -compress none on Option 2 which will give you a very similar file format except the pixel data will be in binary, after the header which remains in ASCII. This is generally faster and smaller.

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • 1
    There's also Method 3 which is raw PPM. You get the speed of raw RGBA but still have the image header (with P6 instead of P3) for remembering the dimensions. It's the same as Method 1 but omitting the `-compress none` option in the initial `convert` step. Note that if depth is greater than 8, the byte in the color samples will be in MSB,LSB order. – Glenn Randers-Pehrson Nov 07 '16 at 12:14
  • @GlennRanders-Pehrson Yes, thank you. I was kind of trying to do one binary and one ASCII to give OP some choice/flexibility. I shall edit your suggestion in - thank you. – Mark Setchell Nov 07 '16 at 12:19
  • @GlennRanders-Pehrson The second `convert` command in methods 2 and 3 specifically extracts the alpha channel. – Mark Setchell Nov 07 '16 at 21:54
  • @GlennRanders-Pehrson You are right - I have corrected it. Not even sure how that got in there because I actually recall typing PGM in my terminal. Thank you. – Mark Setchell Nov 07 '16 at 22:38