11

Looking for some kind of simple tool or process for Windows that will let me convert one or more standard PNGs to premultiplied alpha.

Command line tools are ideal; I have easy access to PIL (Python Imaging Library) and Imagemagick, but will install another tool if it makes life easier.

Thanks!

Ipsquiggle
  • 1,814
  • 1
  • 15
  • 25

5 Answers5

16

Using ImageMagick, as requested:

convert in.png -write mpr:image -background black -alpha Remove mpr:image -compose Copy_Opacity -composite out.png

Thanks @mf511 for the update.

Nuno Cruces
  • 1,584
  • 15
  • 18
  • This doesn't preserve the alpha channel, it just multiplies all the channels with alpha and then seems to discard alpha entirely. I tried this on ImageMagick 7.0.5-4 Q16. – fluffy Apr 22 '17 at 00:44
  • 4
    Yes, but that worked before. Use this as alternative: `convert in.png -background black -alpha Remove in.png -compose Copy_Opacity -composite out.png` – mf511 Apr 23 '17 at 10:57
  • The second command works great! Thanks. – Michael IV Feb 21 '18 at 22:31
14

A more complete version of the cssndrx answer, using slicing in numpy to improve speed:

import Image
import numpy

im = Image.open('myimage.png').convert('RGBA')
a = numpy.fromstring(im.tostring(), dtype=numpy.uint8)
alphaLayer = a[3::4] / 255.0
a[::4]  *= alphaLayer
a[1::4] *= alphaLayer
a[2::4] *= alphaLayer

im = Image.fromstring("RGBA", im.size, a.tostring())

Et voila !

2

I just released a bit of code in Python and in C that does what you are looking for. It's on github: http://github.com/maxme/PNG-Alpha-Premultiplier

The Python version is based on the cssndrx response. C version is based on libpng.

Maxime
  • 2,048
  • 1
  • 27
  • 38
  • Thanks a bunch. :) Going with this answer because I find the code easier to understand than madlag's example, though perhaps not as clever. – Ipsquiggle Aug 07 '11 at 21:04
  • 1
    I like the fact that his code checks if the image is premultiplied. Not requested by the OP but still very nice. – Paul Hildebrandt Apr 23 '12 at 16:40
  • 2
    No wonder the python version is slow - you loop over every single pixel. Francois' python solution is much faster. – Gonzo Mar 05 '13 at 15:25
1

It should be possible to do this through PIL. Here is a rough outline of the steps:

1) Load the image and convert to numpy array

    im = Image.open('myimage.png').convert('RGBA')
    matrix = numpy.array(im)

2) Modify the matrix in place. The matrix is a list of lists of the pixels within each row. Pixels are represented as [r, g, b, a]. Write your own function to convert each [r, g, b, a] pixel to the [r, g, b] value you desire.

3) Convert the matrix back to an image using

    new_im = Image.fromarray(matrix)
cssndrx
  • 773
  • 2
  • 9
  • 17
0

Using PIL only:

def premultiplyAlpha(img):
    # fake transparent image to blend with
    transparent = Image.new("RGBA", img.size, (0, 0, 0, 0))
    # blend with transparent image using own alpha
    return Image.composite(img, transparent, img)