From fredrik at pythonware.com Thu Feb 1 16:36:29 2007 From: fredrik at pythonware.com (Fredrik Lundh) Date: Thu, 1 Feb 2007 16:36:29 +0100 Subject: [Image-SIG] Removing an Alpha Channel References: <8eadd6950701310941l375e51dfj85d955b9d0ef01d8@mail.gmail.com> Message-ID: Jason Van Anden wrote: >I have written an app using PIL that uses alpha channels during processing, > but does not require them once the image is complete. Is there an easy way > to remove existing alpha channels? I suspect there is but the docs don't > make this obvious. im = im.convert("RGB") should do the trick. From jb at langarson.com.au Fri Feb 2 07:32:57 2007 From: jb at langarson.com.au (John Barratt) Date: Fri, 02 Feb 2007 17:32:57 +1100 Subject: [Image-SIG] Comparison of PIL and GD speed for setting pixels through python Message-ID: <45C2DB19.6030309@langarson.com.au> Hi, I've had a need to do some optimisation of some low level pixel setting code, and have as such done some tests of different ways of doing this using PIL and alternatively with gd via ctypes. Ctypes provides a fairly easy way to interface to gd, and allows you to easily use small sections of optimising C code. A summary of the results is below, but basically using ctyles/GD/c is about 20 or so times faster than PIL and the new Image.load, and over 200 times faster than using PIL's ImageDraw.point method. Method Time (s) Times slower than fastest +-----+ +-------+ +------------------------+ ctypes, c, GD 0.00181 1.0 PIL - 'load' 0.03965 21.9 ctypes, GD 0.18710 103.5 PIL - 'point' 0.45009 248.9 A full writeup of this can be found here : http://www.langarson.com.au/blog/?p=10 I hope this is of use, and I look forward to comments, particularly on other ways of doing this with PIL & C, which there undoubtedly are. Cheers, JB. -- John Barratt www.langarson.com.au - Python, Zope, GIS, Weather. From Chris.Barker at noaa.gov Fri Feb 2 21:30:56 2007 From: Chris.Barker at noaa.gov (Christopher Barker) Date: Fri, 02 Feb 2007 12:30:56 -0800 Subject: [Image-SIG] Comparison of PIL and GD speed for setting pixels through python In-Reply-To: <45C2DB19.6030309@langarson.com.au> References: <45C2DB19.6030309@langarson.com.au> Message-ID: <45C39F80.8030700@noaa.gov> John Barratt wrote: > Hi, > I've had a need to do some optimisation of some low level pixel setting > code, and have as such done some tests of different ways of doing this > using PIL and alternatively with gd via ctypes. Have you tried using PIL + numpy -- you can convert a PIL image (some eof them, anyway) to a numpy array, and manipulate it there. Numpy provides a number if efficient ways to do such manipulations. In the most recent PIL, you should be able to convert to/from PIL/numpy without any copying of the data, though I don't think it's been heavily tested. -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov From snaury at gmail.com Sat Feb 3 15:16:59 2007 From: snaury at gmail.com (Alexey Borzenkov) Date: Sat, 3 Feb 2007 17:16:59 +0300 Subject: [Image-SIG] Patch for loading .tga files Message-ID: Hi everyone, As a follow up I found a really small bug with loading .tga files where loader didn't accept 1-bit depth black&white files. See the patch below, but I've also appended it to patch at http://snaury.googlepages.com/Imaging-1.1.6-df-tga.patch (which requires http://snaury.googlepages.com/Imaging-1.1.6-df-bgr.patch) P.S. I wonder why my previous two letters didn't get thru to the mailing list... x_x diff -druN Imaging-1.1.6-orig/PIL/TgaImagePlugin.py Imaging-1.1.6/PIL/TgaImagePlugin.py --- Imaging-1.1.6-orig/PIL/TgaImagePlugin.py Sun Dec 3 14:37:15 2006 +++ Imaging-1.1.6/PIL/TgaImagePlugin.py Sat Feb 3 17:10:04 2007 @@ -70,7 +70,7 @@ # validate header fields if id != 0 or colormaptype not in (0, 1) or\ self.size[0] <= 0 or self.size[1] <= 0 or\ - depth not in (8, 16, 24, 32): + depth not in (1, 8, 16, 24, 32): raise SyntaxError, "not a TGA file" # image mode From snaury at gmail.com Sat Feb 3 15:20:20 2007 From: snaury at gmail.com (Alexey Borzenkov) Date: Sat, 3 Feb 2007 17:20:20 +0300 Subject: [Image-SIG] Inconsistency with BGR packing In-Reply-To: References: Message-ID: Reposting in plain text: ---------- Forwarded message ---------- From: Alexey Borzenkov Date: Feb 3, 2007 2:08 PM Subject: Inconsistency with BGR packing To: image-sig at python.org Hi everyone, Yesterday I've tried using PIL to load and save .bmp files that contain alpha channel. Well, loading was easy to do without even modifying the library: from PIL import BmpImagePlugin BmpImagePlugin.BIT2MODE [32] = ("RGBA", "BGRA") BmpImagePlugin.SAVE["RGBA"] = ("BGRA", 32, 0) However when I tried to save bitmap after loading it I suddenly found that packing into BGRA is not supported. I wonder if this was decided some time ago as "the right thing", or if this was just accidentally left out? (as it seems inconsistent to me that it can unpack BGRA/ABGR, but can't pack it back) Fix for this is pretty trivial, but as it contains tabulation characters in addition to seeing it below you can download it here: http://snaury.googlepages.com/Imaging-1.1.6-df-bgr.patch I hope here is the right place to submit a patch, as PIL site told to do so. And if what's done below is in any way wrong, I'd like to hear your reasons. diff -druN Imaging-1.1.6-orig/libImaging/Pack.c Imaging-1.1.6/libImaging/Pack.c --- Imaging-1.1.6-orig/libImaging/Pack.c Sun Dec 3 14:37:25 2006 +++ Imaging-1.1.6/libImaging/Pack.c Sat Feb 3 09:56:20 2007 @@ -287,6 +287,34 @@ } } +void +ImagingPackBGRA(UINT8* out, const UINT8* in, int pixels) +{ + int i; + /* BGRX, reversed bytes with right padding */ + for (i = 0; i < pixels; i++) { + out[0] = in[B]; + out[1] = in[G]; + out[2] = in[R]; + out[3] = in[A]; + out += 4; in += 4; + } +} + +void +ImagingPackABGR(UINT8* out, const UINT8* in, int pixels) +{ + int i; + /* XBGR, reversed bytes with left padding */ + for (i = 0; i < pixels; i++) { + out[0] = in[A]; + out[1] = in[B]; + out[2] = in[G]; + out[3] = in[R]; + out += 4; in += 4; + } +} + static void packRGBL(UINT8* out, const UINT8* in, int pixels) { @@ -460,6 +488,9 @@ {"RGBA", "RGBA", 32, copy4}, {"RGBA", "RGBA;L", 32, packRGBXL}, {"RGBA", "RGB", 24, ImagingPackRGB}, + {"RGBA", "BGR", 24, ImagingPackBGR}, + {"RGBA", "BGRA", 32, ImagingPackBGRA}, + {"RGBA", "ABGR", 32, ImagingPackABGR}, {"RGBA", "R", 8, band0}, {"RGBA", "G", 8, band1}, {"RGBA", "B", 8, band2}, @@ -469,6 +500,9 @@ {"RGBX", "RGBX", 32, copy4}, {"RGBX", "RGBX;L", 32, packRGBXL}, {"RGBX", "RGB", 32, ImagingPackRGB}, + {"RGBX", "BGR", 32, ImagingPackBGR}, + {"RGBX", "BGRX", 32, ImagingPackBGRX}, + {"RGBX", "XBGR", 32, ImagingPackXBGR}, {"RGBX", "R", 8, band0}, {"RGBX", "G", 8, band1}, {"RGBX", "B", 8, band2}, From snaury at gmail.com Sat Feb 3 15:20:50 2007 From: snaury at gmail.com (Alexey Borzenkov) Date: Sat, 3 Feb 2007 17:20:50 +0300 Subject: [Image-SIG] Patch for saving .tga files In-Reply-To: References: Message-ID: Reposting with plain text: ---------- Forwarded message ---------- From: Alexey Borzenkov Date: Feb 3, 2007 4:55 PM Subject: Patch for saving .tga files To: image-sig at python.org Hi everyone, Another patch from me, this time to save .tga files. You can grab it here: http://snaury.googlepages.com/Imaging-1.1.6-df-tga.patch However I must note that for saving RGBA images you will need my another patch I posted earlier today: http://snaury.googlepages.com/Imaging-1.1.6-df-bgr.patch The .tga saving I did is the very minimal that *seems* to work for me (I based it on code that saves .bmp files), however I'm really not sure about whether I'm saving palette information correctly or not. The main concern is that I don't know how to determine whether image's palette is RGB or RGBA, and thus it's possible to lose alpha information when loading .tga file with BGRA palette and then saving it back (because palette will be saved as BGR). But I hope it'd help others nonetheless. From jb at langarson.com.au Sun Feb 4 11:20:01 2007 From: jb at langarson.com.au (John Barratt) Date: Sun, 04 Feb 2007 21:20:01 +1100 Subject: [Image-SIG] Comparison of PIL and GD speed for setting pixels through python In-Reply-To: <45C39F80.8030700@noaa.gov> References: <45C2DB19.6030309@langarson.com.au> <45C39F80.8030700@noaa.gov> Message-ID: <45C5B351.1000404@langarson.com.au> Christopher Barker wrote: > John Barratt wrote: >> I've had a need to do some optimisation of some low level pixel setting >> code, and have as such done some tests of different ways of doing this >> using PIL and alternatively with gd via ctypes. > > Have you tried using PIL + numpy -- you can convert a PIL image (some > eof them, anyway) to a numpy array, and manipulate it there. Numpy > provides a number if efficient ways to do such manipulations. > > In the most recent PIL, you should be able to convert to/from PIL/numpy > without any copying of the data, though I don't think it's been heavily > tested. I haven't tried it, but did originally think of adding it to the list of things tested. Given this specific example though, where the idea is that a specific method or piece of code is needed to be run for every pixel (not that it actually is in this abstract example), I would think that unless that specific code can be called from, and done in C, that it would perform similarly to the Image.load method. This is because I am assuming the cost of accessing the raw data from Image.load to be similar to that of accessing an array type in numpy. Having said all that though, I'll have a look at adding it to the mix... I think where PIL & numpy would excel is where you have a cases of a number of images with calculations required that could be easily represented as array operations. The examples I am thinking of don't lend themselves to this sort of solution. It is perhaps also possible to reasonably efficiently access the PIL raw data under C as a standard type (eg. a 'flattened' unsigned char* for paletted images) through ctypes, in which case the result time-wise would hopefully be similar, or the same as using gd all the way. I am also finishing a 'real world' example for this sort of problem which may help further clarify further options and their relative benefits & costs. Cheers, JB. From jb at langarson.com.au Sun Feb 4 13:23:41 2007 From: jb at langarson.com.au (John Barratt) Date: Sun, 04 Feb 2007 23:23:41 +1100 Subject: [Image-SIG] Comparison of PIL and GD speed for setting pixels through python In-Reply-To: <45C5B351.1000404@langarson.com.au> References: <45C2DB19.6030309@langarson.com.au> <45C39F80.8030700@noaa.gov> <45C5B351.1000404@langarson.com.au> Message-ID: <45C5D04D.9040603@langarson.com.au> With prompting from Chris, and a little further work in gd, I have updated this comparison further, adding a further gd/ctypes test, this time setting pixel values using the raw pixel data, as well as the start of a test for a numpy/PIL option. Unfortunately it doesn't fully work, at least with the version/s I have. However it does, based on what does work, seem to be relatively slow. The new indicative times look like this : Method Time (s) Times slower than fastest +-----+ +-------+ +------------------------+ ctypes,c,GD raw 0.00082 1.0 ctypes,c,GD 0.00177 2.2 PIL - 'load' 0.03226 39.4 ctypes, GD 0.14428 176.4 PIL, numpy * 0.26271 321.2 PIL - 'point' 0.37180 454.5 Further details are here, including updated code : http://www.langarson.com.au/blog/?p=11 I also fixed a few bugs that affected the image created, but not the timing, and added code to save the files out where possible to further check they were actually doing what was intended. Cheers, JB. -- John Barratt - www.langarson.com.au Python, Zope, GIS, Weather From daniel.nouri at gmail.com Sun Feb 4 20:54:09 2007 From: daniel.nouri at gmail.com (Daniel Nouri) Date: Sun, 04 Feb 2007 20:54:09 +0100 Subject: [Image-SIG] cannot import from PIL when easy_installed Message-ID: <45C639E1.2030003@gmail.com> When you install PIL via easy_install, you cannot import from the PIL module. Is this a bug in PIL or in code that tries to import "from PIL"? >>> import PIL Traceback (most recent call last): File "", line 1, in ? ImportError: No module named PIL >>> import Image #no error This is how I install PIL: $ easy_install --find-links http://www.pythonware.com/products/pil/ \ Imaging There is an open ticket in Plone for this http://dev.plone.org/plone/ticket/5883 Daniel -------------- next part -------------- A non-text attachment was scrubbed... Name: daniel.nouri.vcf Type: text/x-vcard Size: 138 bytes Desc: not available Url : http://mail.python.org/pipermail/image-sig/attachments/20070204/4702e0ff/attachment.vcf From douglas at paradise.net.nz Sun Feb 4 23:43:56 2007 From: douglas at paradise.net.nz (Douglas Bagnall) Date: Mon, 05 Feb 2007 11:43:56 +1300 Subject: [Image-SIG] Comparison of PIL and GD speed for setting pixels through python In-Reply-To: <45C5D04D.9040603@langarson.com.au> References: <45C2DB19.6030309@langarson.com.au> <45C39F80.8030700@noaa.gov> <45C5B351.1000404@langarson.com.au> <45C5D04D.9040603@langarson.com.au> Message-ID: <45C661AC.5090804@paradise.net.nz> hi John, > Method Time (s) Times slower than fastest > +-----+ +-------+ +------------------------+ > ctypes,c,GD raw 0.00082 1.0 > ctypes,c,GD 0.00177 2.2 > PIL - 'load' 0.03226 39.4 > ctypes, GD 0.14428 176.4 > PIL, numpy * 0.26271 321.2 > PIL - 'point' 0.37180 454.5 > You can also access raw PIL image data via C, so your top line, "ctypes,c,GD raw" should be just as applicable to PIL as GD. Or is there some reason this is not so? From memory, you'd pry open the im.im object, and use something like im->image32[y][x] to access each pixel. Also, your C functions boil down to variations of memset. Have you considered trying that? Another option is PIL's paste(colour, box) method. I suspect you are ignoring these two because somewhere you say "one pixel at a time", but as far as I can tell your routines don't allow for that pixel to vary, so there is actually no difference. im.paste(colour, (0, 0, width, height)) is functionally the same as your test functions; inside it probably looks much like your setPixelsRaw. douglas From jb at langarson.com.au Mon Feb 5 00:22:18 2007 From: jb at langarson.com.au (John Barratt) Date: Mon, 05 Feb 2007 10:22:18 +1100 Subject: [Image-SIG] Comparison of PIL and GD speed for setting pixels through python In-Reply-To: <45C661AC.5090804@paradise.net.nz> References: <45C2DB19.6030309@langarson.com.au> <45C39F80.8030700@noaa.gov> <45C5B351.1000404@langarson.com.au> <45C5D04D.9040603@langarson.com.au> <45C661AC.5090804@paradise.net.nz> Message-ID: <45C66AAA.1030606@langarson.com.au> Hi Douglas, Douglas Bagnall wrote: >> Method Time (s) Times slower than fastest >> +-----+ +-------+ +------------------------+ >> ctypes,c,GD raw 0.00082 1.0 >> ctypes,c,GD 0.00177 2.2 >> PIL - 'load' 0.03226 39.4 >> ctypes, GD 0.14428 176.4 >> PIL, numpy * 0.26271 321.2 >> PIL - 'point' 0.37180 454.5 >> > > You can also access raw PIL image data via C, so your top line, > "ctypes,c,GD raw" should be just as applicable to PIL as GD. Or is > there some reason this is not so? From memory, you'd pry open the > im.im object, and use something like im->image32[y][x] to access each > pixel. Ahhh, that is the sort of thing I was wanting to do with PIL, I just didn't know how, though hadn't dug into the source code for PIL either. I will have a look to see if I can get this to fly as well. I would hope that in this case that things should be a similar/same speed between using PIL or gd as the main image object type. The main reason I did it with gd was because I could see a clear path from the documentation to achieve this optimisation. > Also, your C functions boil down to variations of memset. Have you > considered trying that? Another option is PIL's paste(colour, box) > method. I suspect you are ignoring these two because somewhere you > say "one pixel at a time", but as far as I can tell your routines > don't allow for that pixel to vary, so there is actually no > difference. im.paste(colour, (0, 0, width, height)) is functionally > the same as your test functions; inside it probably looks much like > your setPixelsRaw. The code that does the pixel setting in these tests is very simple yes, and deliberately so. It could be done other ways, this was done as a simple test case to get an idea of the overhead of the rest of a system like this. The idea is that each pixel requires some relatively complex piece of code to calculate each value, and one that can't be obtained by simple array/image operations that work on the whole image. I have a 'real world' example that I will finish, and might help show this more clearly. Cheers, JB. -- John Barratt - www.langarson.com.au Python, Zope, GIS, Weather From jb at langarson.com.au Mon Feb 5 11:22:09 2007 From: jb at langarson.com.au (John Barratt) Date: Mon, 05 Feb 2007 21:22:09 +1100 Subject: [Image-SIG] Comparison of PIL and GD speed for setting pixels through python In-Reply-To: <45C66AAA.1030606@langarson.com.au> References: <45C2DB19.6030309@langarson.com.au> <45C39F80.8030700@noaa.gov> <45C5B351.1000404@langarson.com.au> <45C5D04D.9040603@langarson.com.au> <45C661AC.5090804@paradise.net.nz> <45C66AAA.1030606@langarson.com.au> Message-ID: <45C70551.4070008@langarson.com.au> Well after some digging through the PIL source code after the prompting from Douglas, and some tinkering with the python C interface, I have implemented a C based version of the core pixel setting loop using PIL objects. I have also added 'reference' versions using plain python, setting an integer value in the loop, and setting an integer 2D array in a loop. The short of this is that a PIL implementation with C goes faster for larger images (1024x1024), and faster almost overall if you only consider time to actually set the pixels, and not image creation time as well. Fredrik, do you think it would be possible to have a standard API call in PIL that could cleanly & reliably expose the core C pixel data array for use within C (through say ctypes, or back through the python-c api) for optimisations like this? The full breakdown of results, and new source code with the PIL/c implementation can be found here : http://www.langarson.com.au/blog/?p=13 I think that has about exhausted the possible combinations to test, but if anyone has any other suggestions, please let me know. Also if anyone has any ideas as to why the PIL/raw/c version should go so much faster than the gd/raw/c version I would be interested to know, as the core looping code is basically identical... Cheers, JB. -- John Barratt - www.langarson.com.au Python, Zope, GIS, Weather From Chris.Barker at noaa.gov Mon Feb 5 19:28:13 2007 From: Chris.Barker at noaa.gov (Christopher Barker) Date: Mon, 05 Feb 2007 10:28:13 -0800 Subject: [Image-SIG] Comparison of PIL and GD speed for setting pixels through python In-Reply-To: <45C5B351.1000404@langarson.com.au> References: <45C2DB19.6030309@langarson.com.au> <45C39F80.8030700@noaa.gov> <45C5B351.1000404@langarson.com.au> Message-ID: <45C7773D.9010608@noaa.gov> John Barratt wrote: > I haven't tried it, but did originally think of adding it to the list of > things tested. Given this specific example though, where the idea is > that a specific method or piece of code is needed to be run for every > pixel (not that it actually is in this abstract example), I would think > that unless that specific code can be called from, and done in C, that > it would perform similarly to the Image.load method. This is because I > am assuming the cost of accessing the raw data from Image.load to be > similar to that of accessing an array type in numpy. Having said all > that though, I'll have a look at adding it to the mix... Quite true. In fact, your tests make it look like accessing individual pixels in numpy is pretty darn slow. I'm guessing that that's because numpy may be creating a numpy scalar object with every pixel access. > I think where PIL & numpy would excel is where you have a cases of a > number of images with calculations required that could be easily > represented as array operations. The examples I am thinking of don't > lend themselves to this sort of solution. Also true -- but are you sure you couldn't do your pixel-specific calculations as array operations? By the way, you really want to be using numpy 1.0.1, not numpy 0.9.8, numpy was undergoing a lot of flux before 1.0 came out. Also, it looks like your code wouldn't work anyway: data = numpy.resize(numpy.array(0),outputSize) for x in range(outputSize[0]): for y in range(outputSize[1]): data[x,y] = colourI This creates a 2-d array of 32bit integers, which isn't going to match an RBG array. You'd need to either use RGBA, or use an WxHx3 array of bytes: data = numpy.zeros(outputSize[0], outputSize[1], 3, dtype=numpy.ubyte) However, that would only make it slower! I am a bit surprised that it is as slow as that. John Barratt wrote: >> You can also access raw PIL image data via C, so your top line, >> "ctypes,c,GD raw" should be just as applicable to PIL as GD. Or is >> there some reason this is not so? From memory, you'd pry open the >> im.im object, and use something like im->image32[y][x] to access each >> pixel. > Ahhh, that is the sort of thing I was wanting to do with PIL, I just > didn't know how, There is a movement afoot (mostly us numpy folks) to get a basic n-d array object into the standard Python library. The goal is that all packages that need an nd-array of data (such as PIL, etc) could use the same thing, and then they'd all have the same C API for accessing the data -- this looks like another good argument for that! > The idea is that each pixel requires some relatively complex > piece of code to calculate each value, and one that can't be obtained by > simple array/image operations that work on the whole image. careful here -- if your "relatively complex" piece of code takes substantially longer than the pixel setting, then all this work is for naught -- though we're all learning something from it! by the way, numpy can do more than "simple array" operations -- so it still may help. -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov From douglas at paradise.net.nz Tue Feb 6 00:59:48 2007 From: douglas at paradise.net.nz (Douglas Bagnall) Date: Tue, 06 Feb 2007 12:59:48 +1300 Subject: [Image-SIG] Comparison of PIL and GD speed for setting pixels through python In-Reply-To: <45C70551.4070008@langarson.com.au> References: <45C2DB19.6030309@langarson.com.au> <45C39F80.8030700@noaa.gov> <45C5B351.1000404@langarson.com.au> <45C5D04D.9040603@langarson.com.au> <45C661AC.5090804@paradise.net.nz> <45C66AAA.1030606@langarson.com.au> <45C70551.4070008@langarson.com.au> Message-ID: <45C7C4F4.6090704@paradise.net.nz> John Barratt wrote: > I think that has about exhausted the possible combinations to test, but > if anyone has any other suggestions, please let me know. Also if anyone > has any ideas as to why the PIL/raw/c version should go so much faster > than the gd/raw/c version I would be interested to know, as the core > looping code is basically identical... > um.. cache locality? With GD you have for (u=0; u References: <45C2DB19.6030309@langarson.com.au> <45C39F80.8030700@noaa.gov> <45C5B351.1000404@langarson.com.au> <45C7773D.9010608@noaa.gov> Message-ID: <45C7D646.306@langarson.com.au> Hi Chris, Christopher Barker wrote: >> I think where PIL & numpy would excel is where you have a cases of a >> number of images with calculations required that could be easily >> represented as array operations. The examples I am thinking of don't >> lend themselves to this sort of solution. > > Also true -- but are you sure you couldn't do your pixel-specific > calculations as array operations? Well, certainly not simple array operations, I have an example I will finish (hill shading) that perhaps could be done with array operations, but would I think still require a large number of them, making it still inefficient. > By the way, you really want to be using numpy 1.0.1, not numpy 0.9.8, > numpy was undergoing a lot of flux before 1.0 came out. OK, I will update my version. > Also, it looks like your code wouldn't work anyway: > > data = numpy.resize(numpy.array(0),outputSize) > for x in range(outputSize[0]): > for y in range(outputSize[1]): > data[x,y] = colourI > > This creates a 2-d array of 32bit integers, which isn't going to match > an RBG array. You'd need to either use RGBA, or use an WxHx3 array of > bytes: > > data = numpy.zeros(outputSize[0], outputSize[1], 3, dtype=numpy.ubyte) > > However, that would only make it slower! I am a bit surprised that it is > as slow as that. OK, thanks. I was perhaps guessing at what was required here, and since I couldn't get the output to work I couldn't tell it was actually broken. I'll revisit this when I can get numpy working with PIL, perhaps the newer version will help. > There is a movement afoot (mostly us numpy folks) to get a basic n-d > array object into the standard Python library. The goal is that all > packages that need an nd-array of data (such as PIL, etc) could use the > same thing, and then they'd all have the same C API for accessing the > data -- this looks like another good argument for that! mmm that would be nice. Would be nice to be able to combine python with the efficiency of C more easily for tasks like this! >> The idea is that each pixel requires some relatively complex piece of >> code to calculate each value, and one that can't be obtained by simple >> array/image operations that work on the whole image. > > careful here -- if your "relatively complex" piece of code takes > substantially longer than the pixel setting, then all this work is for > naught -- though we're all learning something from it! Yes, true. It could be a relatively minor cost at the end of the day if the per-pixel operation is too costly. But there are actually two motivations here : - If the per-pixel operation isn't too costly, then you get a real noticeable benefit of lower pixel-access overhead. - Even if the per-pixel operation is relatively costly, with this method you can easily implement that per-pixel operation in C because the core pixel access loop is in C (with PIL or gd at the python level). This in turn should make it run significantly faster than it's pure python counterpart. This perhaps works only with the assumption that it isn't too much effort to write/rewrite that particular operation in C. > by the way, numpy can do more than "simple array" operations -- so it > still may help. OK. It may indeed be able to do something more effectively with the next example. Thanks for the comments, JB. -- John Barratt - www.langarson.com.au Python, Zope, GIS, Weather From jb at langarson.com.au Tue Feb 6 02:43:58 2007 From: jb at langarson.com.au (John Barratt) Date: Tue, 06 Feb 2007 12:43:58 +1100 Subject: [Image-SIG] Comparison of PIL and GD speed for setting pixels through python In-Reply-To: <45C7C4F4.6090704@paradise.net.nz> References: <45C2DB19.6030309@langarson.com.au> <45C39F80.8030700@noaa.gov> <45C5B351.1000404@langarson.com.au> <45C5D04D.9040603@langarson.com.au> <45C661AC.5090804@paradise.net.nz> <45C66AAA.1030606@langarson.com.au> <45C70551.4070008@langarson.com.au> <45C7C4F4.6090704@paradise.net.nz> Message-ID: <45C7DD5E.5080606@langarson.com.au> Hi Douglas, Douglas Bagnall wrote: > um.. cache locality? With GD you have > > for (u=0; u for (v=0; v d[v][u] = colour; > } > } > > which goes through every row for each column, jumping back and forth in > memory. You need to switch the order of the loops, like you have in the > PIL example: > > for (u=0; u for (v=0; v data[u][v] = colour; > } > } Ahhh, thanks, that makes sense! The data is arranged differently in the two examples, but not my loops... Changing this around swings the best performer around the other way. For a 512x512 image indicative results now looks like : Method Time (s) Times slower than fastest +-----+ +-------+ +------------------------+ ctypes,c,GD raw 0.00174 1.0 PIL,load/c/raw 0.00356 2.0 ... However, if you now exclude image creation time, the times are basically the same for both the c,raw methods, as would be expected. :) > ...which, BTW, as written, would not be so successful on non-square images. errr, yes, fixed. *red face* Thank you! :) I've updated the code linked from here with these changes : http://www.langarson.com.au/blog/?p=13 > However, this shows how far the benchmark has got from real world usage. > As Chris Barker pointed out, if you are doing any kind of work to find > your pixels, these effects would become negligible. Yes, true. As I mentioned in the response to Chris's post though, there are cases I think where this will have a direct benefit, and if not, there will also often be an indirect one due to the ability to easily code that more complex operation in C than python, and also have it called efficiently direct from C. > Have you looked at PyGame? it seems to have drawing commands too. No, I haven't, and it may be worth looking at. However I primarily wanted to look at ways to speed up CPU hogging operations in particular application with the likes of PIL and gd, and still be able to get the benefit of direct python access to the other typical 'Imaging Library' type methods such as drawing text, lines, etc. I suppose PyGame will have a lot of this, but perhaps not the breadth of more traditional image operations that PIL, or even gd provide. Thanks for you comments, Cheers, JB. -- John Barratt - www.langarson.com.au Python, Zope, GIS, Weather From jb at langarson.com.au Tue Feb 6 05:50:50 2007 From: jb at langarson.com.au (John Barratt) Date: Tue, 06 Feb 2007 15:50:50 +1100 Subject: [Image-SIG] Two PIL based Hill Shading Implementations, using Python & Python/C. Message-ID: <45C8092A.4020807@langarson.com.au> This is a follow up on my previous posts about PIL/gd speed comparisons, which is perhaps now a bit of a misnomer. It is now really just a C/python speed comparison for custom intensive image operations given it is clearly possible to access the same sort of raw data with both gd and PIL within C. My real end goal is to find the best way to make CPU intensive imaging apps go *much* faster, but still be able to use python & PIL/gd for the bulk of the code. Specifically I have created two implementations here of a hill shading algorithm using PIL, with one version using pure python, the other using python and a c implementation for the core loop. For this particular implementation the relative speedup for the specific example given was about 20 times for the python/c version over the pure python version. A 2300x1900 input image yielded essentially the same speedup ratio. It wasn't too hard to do the core C part of the code since it was so similar to the python version. It was a little fiddly getting the python-c interface code together, and navigating down to the raw data inside PIL. However now this is done this should not be a real hindrance to any further implementations like this. Full details including the code, and sample input & output images are here : http://www.langarson.com.au/blog/?p=14 I'm not sure how easily this implemented using array operations in numpy given nature of the algorithm, and in turn how relatively efficient it would be. Comments welcome. :) Cheers, JB. -- John Barratt - www.langarson.com.au Python, Zope, GIS, Weather From whenney at gmail.com Tue Feb 6 20:09:59 2007 From: whenney at gmail.com (Will Henney) Date: Tue, 6 Feb 2007 19:09:59 +0000 (UTC) Subject: [Image-SIG] =?utf-8?q?Two_PIL_based_Hill_Shading_Implementations?= =?utf-8?q?=2C=09using_Python_=26_Python/C=2E?= References: <45C8092A.4020807@langarson.com.au> Message-ID: Hi John How about this for a numpy implementation? Runs nearly as fast as the C version on my mac (1.58 vs 1.16 secs). def hillShadeNumPy(filenameIn, filenameOut, scale=1.0, azdeg=315.0, altdeg=45.0): ''' Create a hill shade version of the given image using numpy ''' from numpy import sin, cos, hypot, arctan, arctan2, pi dScale = (1.0 * scale) # convert alt, az to radians az = azdeg*pi/180.0 alt = altdeg*pi/180.0 (img, data, imgS, dataS) = initialiseImages(filenameIn) # get the image data as a numpy array of floats adata = N.asarray(img).astype('float') # gradient in x and y directions dx, dy = N.gradient(adata/dScale) slope = 0.5*pi - arctan(hypot(dx, dy)) aspect = arctan2(dx, dy) c = sin(alt)*sin(slope) + cos(alt)*cos(slope)*cos(-az - aspect - 0.5*pi) c = N.where(c > 0.0, c*255.0, 0.0) imgS = Image.fromarray(c.astype('uint8')) imgS.save(filenameOut,'PNG') Cheers Will From douglas at paradise.net.nz Tue Feb 6 22:38:26 2007 From: douglas at paradise.net.nz (Douglas Bagnall) Date: Wed, 07 Feb 2007 10:38:26 +1300 Subject: [Image-SIG] Two PIL based Hill Shading Implementations, using Python & Python/C. In-Reply-To: <45C8092A.4020807@langarson.com.au> References: <45C8092A.4020807@langarson.com.au> Message-ID: <45C8F552.5080901@paradise.net.nz> John Barratt wrote: > http://www.langarson.com.au/blog/?p=14 > This is an observation, not a recommendation, but you could *almost* do all of this in pure PIL, without explicit loops. You could find the slope like so: dxfilter = ImageFilter((3,3), [1, 0, -1, 2, 0, -2, 1, 0, -1], 1) dyfilter = ImageFilter((3,3), [-1, -2, -1, 0, 0, 0, 1, 2, 1], 1) im_dx = img.filter(dxfilter) im_dy = img.filter(dyfilter) im_slope = ImageMath.eval("(a*a + b*b) ** 0.5)", a=im_dx, b=im_dy) The simple trig functions could use Image.point: def _sin(x): return 128 + sin(x) *127 #scaled to save precision im_sin_slope = im_slope.point(_sin) which should be quicker (though less accurate) than other methods, because it builds a lookup table rather than calculating each point. The tricky one looks to be the atan2 used to calculate the aspect. Either it needs to be split into two functions, one calculating atan(dy/dx), and the other calculating the correct quadrant, or it needs to be approximated using arithmetic in ImageMath. After that it is just a matter of back-scaling, multiplying and summing, which ImageMath.eval and other functions can do. but, as I said, I don't recommend it. douglas From RICHARD.LOURETTE at itt.com Wed Feb 7 22:01:16 2007 From: RICHARD.LOURETTE at itt.com (Lourette, Richard W - SSD) Date: Wed, 7 Feb 2007 16:01:16 -0500 Subject: [Image-SIG] 16bit to 8bit conversion with a lut Message-ID: <29040DA05CCC0A49B6A34963971E2B1F0106FAF9@ssdrocxch2.SSD.de.ittind.com> Here is the code that I am using to perform a look up table conversion from 16 bit imagery to 8 bit imagery. tif_image = "in.tif" #16 bit tiff image # create 65536 entry lut. All 255s for demonstration purposes lut = [] lut = [255] * 65536 print len(lut) # 65536, to make sure it is the right length im1 = Image.open(tif_image) print im1.mode # "I;16" im2 = im1.point(lut, "L") im2.save("out.tif") print "done" When I run this, I get the following error: Unhandled exception while debugging... Traceback (most recent call last): File "D:\Projects\Stare Python Development\ProcessImage.py", line 34, in ? im2 = im1.point(lut, "L") File "C:\Python24\Lib\site-packages\PIL\Image.py", line 1109, in point return self._new(self.im.point(lut, mode)) ValueError: wrong number of lut entries I would rather not have to iterate through all the pixels with a loop since the images I am working with are 11Mpixels in size. I am running PIL 1.1.6 Thanks. Rich ************************************ This e-mail and any files transmitted with it are proprietary and intended solely for the use of the individual or entity to whom they are addressed. If you have received this e-mail in error please notify the sender. Please note that any views or opinions presented in this e-mail are solely those of the author and do not necessarily represent those of ITT, Inc. The recipient should check this e-mail and any attachments for the presence of viruses. ITT accepts no liability for any damage caused by any virus transmitted by this e-mail. ************************************ From jb at langarson.com.au Thu Feb 8 12:37:47 2007 From: jb at langarson.com.au (John Barratt) Date: Thu, 08 Feb 2007 22:37:47 +1100 Subject: [Image-SIG] Two PIL based Hill Shading Implementations, using Python & Python/C. In-Reply-To: References: <45C8092A.4020807@langarson.com.au> Message-ID: <45CB0B8B.90900@langarson.com.au> Hi Will, Will Henney wrote: > How about this for a numpy implementation? Runs nearly as fast as the C version > on my mac (1.58 vs 1.16 secs). This is great! I get about 0.34 vs 0.55. The numpy implementation is darn good for a python only implementation. There is a subtle difference in the output though, this version seems to create a what appears as a slightly 'noisier' result, the python and C versions I did were identical to the eye at least at 1:1. Not sure exactly why this would be perhaps a value is clipping somewhere? Could be also there is a consistent error in my two implementations. I upgraded my numpy to the latest version and now it works with the latest PIL, so I will have to revisit the other simple pixel setting test that didn't work at all for me before. I have also looked at the performance python article (http://www.scipy.org/PerformancePython) that was forwarded through to me (thanks Sebastian!) which looks like it opens up yet more convenient performance options with the weave modules, particularly now that I have numpy working with PIL. Lots to explore still it seems! Thanks for the example, Cheers, JB. > def hillShadeNumPy(filenameIn, filenameOut, scale=1.0, azdeg=315.0, altdeg=45.0): > ''' Create a hill shade version of the given image using numpy ''' > from numpy import sin, cos, hypot, arctan, arctan2, pi > > dScale = (1.0 * scale) > # convert alt, az to radians > az = azdeg*pi/180.0 > alt = altdeg*pi/180.0 > (img, data, imgS, dataS) = initialiseImages(filenameIn) > > # get the image data as a numpy array of floats > adata = N.asarray(img).astype('float') > # gradient in x and y directions > dx, dy = N.gradient(adata/dScale) > slope = 0.5*pi - arctan(hypot(dx, dy)) > aspect = arctan2(dx, dy) > c = sin(alt)*sin(slope) + cos(alt)*cos(slope)*cos(-az - aspect - 0.5*pi) > c = N.where(c > 0.0, c*255.0, 0.0) > imgS = Image.fromarray(c.astype('uint8')) > imgS.save(filenameOut,'PNG') -- John Barratt - www.langarson.com.au Python, Zope, GIS, Weather From jb at langarson.com.au Thu Feb 8 12:49:44 2007 From: jb at langarson.com.au (John Barratt) Date: Thu, 08 Feb 2007 22:49:44 +1100 Subject: [Image-SIG] Two PIL based Hill Shading Implementations, using Python & Python/C. In-Reply-To: <45C8F552.5080901@paradise.net.nz> References: <45C8092A.4020807@langarson.com.au> <45C8F552.5080901@paradise.net.nz> Message-ID: <45CB0E58.6010703@langarson.com.au> Hi Douglas, It's good to see an example (albeit partial) like this, I haven't really used ImageMath and ImageFilter. Would be interesting to compare with equivalent numpy implementations performance-wise for some image processing problems. Cheers, JB. Douglas Bagnall wrote: > John Barratt wrote: > >> http://www.langarson.com.au/blog/?p=14 >> > > This is an observation, not a recommendation, but you could *almost* do > all of this in pure PIL, without explicit loops. You could find the > slope like so: > > dxfilter = ImageFilter((3,3), [1, 0, -1, > 2, 0, -2, > 1, 0, -1], 1) > dyfilter = ImageFilter((3,3), [-1, -2, -1, > 0, 0, 0, > 1, 2, 1], 1) > > im_dx = img.filter(dxfilter) > im_dy = img.filter(dyfilter) > im_slope = ImageMath.eval("(a*a + b*b) ** 0.5)", a=im_dx, b=im_dy) > > The simple trig functions could use Image.point: > > def _sin(x): > return 128 + sin(x) *127 #scaled to save precision > im_sin_slope = im_slope.point(_sin) > > which should be quicker (though less accurate) than other methods, > because it builds a lookup table rather than calculating each point. > > The tricky one looks to be the atan2 used to calculate the aspect. > Either it needs to be split into two functions, one calculating > atan(dy/dx), and the other calculating the correct quadrant, or it needs > to be approximated using arithmetic in ImageMath. > > After that it is just a matter of back-scaling, multiplying and summing, > which ImageMath.eval and other functions can do. > > but, as I said, I don't recommend it. > > > douglas > -- John Barratt - www.langarson.com.au Python, Zope, GIS, Weather From phycomp at gmail.com Thu Feb 8 14:52:20 2007 From: phycomp at gmail.com (Samuel Lu) Date: Thu, 8 Feb 2007 21:52:20 +0800 Subject: [Image-SIG] Soft-edge a image. Message-ID: <4dc592010702080552r3b36c0eate4179109f69b7226@mail.gmail.com> Dear all PIL fans, i'm a newbie in using the PIL. if i'd like to soft-edge a image , i.e. blur the surrounding of a jpg format image, how can i use the filter module? what does the python code looks like? Any help is highly appreciated. Best Regards, Samuel at Taiwan From peter at monicol.co.uk Sun Feb 11 21:19:27 2007 From: peter at monicol.co.uk (Peter Mott) Date: Sun, 11 Feb 2007 20:19:27 +0000 Subject: [Image-SIG] Image fonts Message-ID: <45CF7A4F.9010401@monicol.co.uk> I want to draw text onto a JPEG image. On Windows I have TrueType fonts and font = ImageFont.truetype("Arial.ttf",12) works. On my ISP's FreeBSD system it does not - the resource is unknown. So I need to supply PIL with some fonts - but I have not the foggiest how to go about this. The BSD is "FreeBSD 4.8-STABLE ", Python is "Python 2.3.4" and I think that the PIL library is 1.1.5. I am pretty sure PIL is at 1.1.5 (is there anyway I can find this out?). I presently can't even see how to find out what fonts are available let alone install additonal ones. Any help much appreciated. Peter From aspineux at gmail.com Sun Feb 11 23:30:34 2007 From: aspineux at gmail.com (Alain Spineux) Date: Sun, 11 Feb 2007 23:30:34 +0100 Subject: [Image-SIG] some bug in PIL, with test case Message-ID: <71fe4e760702111430h56714e54v9bfdc66e4f9d92fb@mail.gmail.com> Hello I used PIL for the first time and found some bugs. The code and description follow. The main problem is that drawing a line from A to B dont get the same result as from B to A! And because of this (I thing) the color of a polygon overflow it's outline. And last i found the size of a rotated image unpredictable! The error is only of one 1 pixel, but this is enough to have to image cover another or have a blank between them. Best regards Alain Here is the code def pil_bugs(): imgs=[] # here the color of the polygone overflow the outline ! polygon=[(82, 39), (81, 8), (76, 0), (42, 0), (37, 7), (47, 39)] img=Image.new('RGB', (100, 100), (255, 255, 255)) draw=ImageDraw.Draw(img) draw.polygon(polygon, fill=(255,128,128), outline=(0,0,0)) del draw imgs.append(img) # here I draw multiple line with different gradient # first from "center" to outside # and second from outside to inside # the second line don't match exactly the first one ! img=Image.new('RGB', (200, 200), (255, 255, 255)) w, h=img.size cx, cy=w/2, h/2 pts=[ (80,0), (80,20), (80,40), (80, 60), (80,80) ] draw=ImageDraw.Draw(img) for x, y in pts: draw.line((cx, cy, cx+x, cy+y), (0,0,0)) draw.line((cx, cy, cx+y, cy+x), (0,0,0)) draw.line((cx, cy, cx-x, cy+y), (0,0,0)) draw.line((cx, cy, cx-y, cy+x), (0,0,0)) draw.line((cx, cy, cx-x, cy-y), (0,0,0)) draw.line((cx, cy, cx-y, cy-x), (0,0,0)) draw.line((cx, cy, cx+x, cy-y), (0,0,0)) draw.line((cx, cy, cx+y, cy-x), (0,0,0)) draw.line((cx+x, cy+y, cx, cy), (255,0,0)) draw.line((cx+y, cy+x, cx, cy), (255,0,0)) draw.line((cx-x, cy+y, cx, cy), (255,0,0)) draw.line((cx-y, cy+x, cx, cy), (255,0,0)) draw.line((cx-x, cy-y, cx, cy), (255,0,0)) draw.line((cx-y, cy-x, cx, cy), (255,0,0)) draw.line((cx+x, cy-y, cx, cy), (255,0,0)) draw.line((cx+y, cy-x, cx, cy), (255,0,0)) del draw imgs.append(img) # this test compare the logical size of a rotated image with the real one img=Image.new('RGB', (100, 27), (255, 255, 255)) w, h=img.size for alpha in range(0, 90, 1): riw, rih=img.rotate(alpha, Image.BICUBIC, True).size u=h*math.sin(math.radians(alpha))+w*math.cos(math.radians(alpha)) v=w*math.sin(math.radians(alpha))+h*math.cos(math.radians(alpha)) rfw, rfh=int(math.floor(u)), int(math.floor(v)) rcw, rch=int(math.ceil(u)), int(math.ceil(v)) print '%3d: %3dx%3d %5.1fx%5.1f floor %-2d %-2d ceil %-2d %-2d' % ( alpha, riw, rih, u, v, riw-rfw , rih-rfh, riw-rcw, rih-rch) # this is not a bug, but why to mix size and vertices ? # 99!=100 this could disturb the user that must make +1 or -1 img=Image.new('RGB', (100, 100), (255, 255, 255)) img=img.transform(img.size, Image.MESH, [((0, 0, 100, 100), (0,0,0,99,99,99,99,0))], Image.BICUBIC) # imgs.append(img) return imgs -- Alain Spineux aspineux gmail com May the sources be with you From goat at tirfa.com Tue Feb 13 03:21:29 2007 From: goat at tirfa.com (goat at tirfa.com) Date: Mon, 12 Feb 2007 21:21:29 -0500 Subject: [Image-SIG] TrueType fonts under PIL Message-ID: <20070212212129.x7l21jahokks0s0o@desmond.asmallorange.com> I have been writing a python script that automatically makes button images from text files and I have some questions about the TrueType font rendering in PIL 1.1.6 under Python 2.5 under Win32 (used the installer). I have been having some issues with glyphs either not rendering completely or not rendering at all(the ones that I have noticed are '_' and the descender (http://en.wikipedia.org/wiki/Descender) for lower case 'g'). After some playing around, I found that this seems to be mostly dependent on font size. Depending on which font I use, the size at which everything renders correctly changes but they render correctly at some sizes and don't when I use other sizes. Does anyone have any suggestions on what I can do to improve TrueType font rendering without changing the font size? Thanks for your time, Tim Environment Information: Windows XP SP2 Python 2.5 (.msi version from python.org) PIL 1.1.6 (downloaded .msi for python 2.5) Font: I've tried several, but the one that I have been using most is IPA Mona Gothic (ipag-mona.ttf) which is a Japanese language font available from http://www.geocities.jp/ipa_mona/ and I believe that it is used in several FOSS projects. From rijoth at gmx.de Tue Feb 13 13:48:00 2007 From: rijoth at gmx.de (=?ISO-8859-1?Q?Joachim_Th=F6ne?=) Date: Tue, 13 Feb 2007 13:48:00 +0100 Subject: [Image-SIG] TrueType fonts under PIL In-Reply-To: <20070212212129.x7l21jahokks0s0o@desmond.asmallorange.com> References: <20070212212129.x7l21jahokks0s0o@desmond.asmallorange.com> Message-ID: <45D1B380.20205@gmx.de> goat at tirfa.com schrieb: > I have been writing a python script that automatically makes button > images from text files and I have some questions about the TrueType > font rendering in PIL 1.1.6 under Python 2.5 under Win32 (used the > installer). > > I have been having some issues with glyphs either not rendering > completely or not rendering at all(the ones that I have noticed are > '_' and the descender (http://en.wikipedia.org/wiki/Descender) for > lower case 'g'). After some playing around, I found that this seems to > be mostly dependent on font size. Depending on which font I use, the > size at which everything renders correctly changes but they render > correctly at some sizes and don't when I use other sizes. > > Does anyone have any suggestions on what I can do to improve TrueType > font rendering without changing the font size? > > Thanks for your time, > > Tim > > Environment Information: > Windows XP SP2 > Python 2.5 (.msi version from python.org) > PIL 1.1.6 (downloaded .msi for python 2.5) > > Font: I've tried several, but the one that I have been using most is > IPA Mona Gothic (ipag-mona.ttf) which is a Japanese language font > available from http://www.geocities.jp/ipa_mona/ and I believe that it > is used in several FOSS projects. > _______________________________________________ > Image-SIG maillist - Image-SIG at python.org > http://mail.python.org/mailman/listinfo/image-sig > > Hello Tim, I've loaded ipag-mona.ttf fontfile into PIL via the aggdraw library (an extension for Pil, that does not use PIL to load the font) with an identical result to yours. Migtht be that the fontfile is buggy, I've never had troubles with displaying .ttf fonts in PIL. Joachim From jason at smileproject.com Tue Feb 13 18:48:47 2007 From: jason at smileproject.com (Jason Van Anden) Date: Tue, 13 Feb 2007 12:48:47 -0500 Subject: [Image-SIG] crop question Message-ID: <8eadd6950702130948x131ad6e3wcb0913313de29c4c@mail.gmail.com> I am trying to take an existing image and split it into equally sized tiles. When I try to save a "cropped" image I get the following error: "tile cannot extend outside image" The first pass saves the first tile correctly, the second one chokes and blurts the error. Following is some code to illustrate my confusion: original_image = Image.open("big_image.tif") # math stuff w, h = orig.size self.tile_width = w = w/self.tiles_across self.tile_height = h = h/self.tiles_down for y in range (self.tiles_down): for x in range (self.tiles_across): box = (x * w, y * h, w, h) tim = original_image.crop(box) tim.save("test.tif") Advice super appreciated! Thank You ~ j From ken at seehart.com Tue Feb 13 23:12:26 2007 From: ken at seehart.com (Ken Seehart) Date: Tue, 13 Feb 2007 14:12:26 -0800 Subject: [Image-SIG] crop question In-Reply-To: <8eadd6950702130948x131ad6e3wcb0913313de29c4c@mail.gmail.com> References: <8eadd6950702130948x131ad6e3wcb0913313de29c4c@mail.gmail.com> Message-ID: <45D237CA.5000100@seehart.com> Jason Van Anden wrote: > I am trying to take an existing image and split it into equally sized > tiles. When I try to save a "cropped" image I get the following > error: > > "tile cannot extend outside image" > > The first pass saves the first tile correctly, the second one chokes > and blurts the error. > > Following is some code to illustrate my confusion: > > original_image = Image.open("big_image.tif") > > # math stuff > w, h = orig.size > self.tile_width = w = w/self.tiles_across > self.tile_height = h = h/self.tiles_down > > for y in range (self.tiles_down): > > for x in range (self.tiles_across): > > box = (x * w, y * h, w, h) > tim = original_image.crop(box) > tim.save("test.tif") > > Advice super appreciated! > > Thank You ~ j > Crop uses right and lower instead of width and height for the last two elements of the box. crop *im.crop(box)* => image Returns a rectangular region from the current image. The box is a 4-tuple defining the left, upper, right, and lower pixel coordinate. - Ken From goat at tirfa.com Thu Feb 15 01:21:33 2007 From: goat at tirfa.com (goat at tirfa.com) Date: Wed, 14 Feb 2007 19:21:33 -0500 Subject: [Image-SIG] TrueType fonts under PIL In-Reply-To: <45D1B380.20205@gmx.de> References: <20070212212129.x7l21jahokks0s0o@desmond.asmallorange.com> <45D1B380.20205@gmx.de> Message-ID: <20070214192133.7meapp5008scscok@desmond.asmallorange.com> I think that I figured out why things didn't look like I wanted. I am writing text on a template gif image and wasn't converting it to a RGB image. In order to get the text to show up, I was changing the image's palette to include black (rgb(0,0,0)) and then using that new palette color to write text on the image. Since the truetype fonts seem to be rendered in greyscale rather than monochrome, anything that wasn't pure black wouldn't show up on the final image. When I work with RGB bmp files, everything looks wonderful but looks horrible when I re-encode the bmp to gif. So the moral of the story seems to be: be careful about writing truetype text in monochrome. Tim Quoting Joachim Th?ne : > goat at tirfa.com schrieb: >> I have been writing a python script that automatically makes button >> images from text files and I have some questions about the >> TrueType font rendering in PIL 1.1.6 under Python 2.5 under Win32 >> (used the installer). >> >> I have been having some issues with glyphs either not rendering >> completely or not rendering at all(the ones that I have noticed are >> '_' and the descender (http://en.wikipedia.org/wiki/Descender) >> for lower case 'g'). After some playing around, I found that this >> seems to be mostly dependent on font size. Depending on which font >> I use, the size at which everything renders correctly changes but >> they render correctly at some sizes and don't when I use other >> sizes. >> >> Does anyone have any suggestions on what I can do to improve >> TrueType font rendering without changing the font size? >> >> Thanks for your time, >> >> Tim >> >> Environment Information: >> Windows XP SP2 >> Python 2.5 (.msi version from python.org) >> PIL 1.1.6 (downloaded .msi for python 2.5) >> >> Font: I've tried several, but the one that I have been using most >> is IPA Mona Gothic (ipag-mona.ttf) which is a Japanese language >> font available from http://www.geocities.jp/ipa_mona/ and I >> believe that it is used in several FOSS projects. >> _______________________________________________ >> Image-SIG maillist - Image-SIG at python.org >> http://mail.python.org/mailman/listinfo/image-sig >> >> > Hello Tim, > I've loaded ipag-mona.ttf fontfile into PIL via the aggdraw library (an > extension for Pil, that does not use PIL to load the font) with an > identical result to yours. Migtht be that the fontfile is buggy, I've > never had troubles with displaying .ttf fonts in PIL. > > Joachim From matt at tplus1.com Fri Feb 16 20:29:03 2007 From: matt at tplus1.com (Matthew Wilson) Date: Fri, 16 Feb 2007 14:29:03 -0500 Subject: [Image-SIG] How to overlay a mostly transparent image over another image? Message-ID: <20070216192903.GA9417@mwilson.umlcoop.net> I have a bunch of 50x50 PNG files that show a little product. I have some other 50x50 PNG files that are transparent except for the bottom right corner, which has some text like "new!" or "fun!". I want to create a new file that contains the original product thumbnail, plus the mostly transparent image added over. I figure this is a very straightforward operation, but I'm not getting anywhere yet. This is what I've tried so far: In [93]: a = Image.open('a.png') In [94]: a.info Out[94]: {} In [95]: a.size Out[95]: (50, 50) In [96]: a.mode Out[96]: 'RGB' In [97]: ff = Image.open('freeframe.png') In [98]: ff.info Out[98]: {'Creation Time': '02/16/07', 'Software': 'Macromedia Fireworks 8', 'dpi': (71, 71), 'transparency': 0} In [99]: ff.mode Out[99]: 'P' In [100]: ff.size Out[100]: (50, 50) In [101]: ImageChops.add(a, ff) --------------------------------------------------------------------------- Traceback (most recent call last) C:\Documents and Settings\mwilson\My Documents\pil-fun\ in () C:\Python25\lib\site-packages\PIL\ImageChops.py in add(image1, image2, scale, offset) 175 image1.load() 176 image2.load() --> 177 return image1._new(image1.im.chop_add(image2.im, scale, offset)) 178 179 ## : images do not match In [102]: a2 = a.convert(mode='P') In [103]: ImageChops.add(a2, ff) Out[103]: In [104]: _103.show() The image that I see is a grayscale image of just the a.png file. I can't see the first image. I'm probably making lots of rookie mistakes. All comments welcome. Matt -- A better way of running series of SAS programs: http://overlook.homelinux.net/wilsonwiki/SasAndMakefiles From maxerickson at gmail.com Fri Feb 16 22:07:38 2007 From: maxerickson at gmail.com (Max Erickson) Date: Fri, 16 Feb 2007 21:07:38 +0000 (UTC) Subject: [Image-SIG] How to overlay a mostly transparent image over another image? References: <20070216192903.GA9417@mwilson.umlcoop.net> Message-ID: Matthew Wilson wrote: > I have a bunch of 50x50 PNG files that show a little product. I > have some other 50x50 PNG files that are transparent except for > the bottom right corner, which has some text like "new!" or > "fun!". > > I want to create a new file that contains the original product > thumbnail, plus the mostly transparent image added over. > > I figure this is a very straightforward operation, but I'm not > getting anywhere yet. > > This is what I've tried so far: ... > Maybe you want im.paste? See the section about it at: http://effbot.org/imagingbook/image.htm max From aspineux at gmail.com Sat Feb 17 02:48:22 2007 From: aspineux at gmail.com (Alain Spineux) Date: Sat, 17 Feb 2007 02:48:22 +0100 Subject: [Image-SIG] problem for drawing char J alone using font VeraIt.ttf Message-ID: <71fe4e760702161748m3a418596hc42fd1ba926a1f4f@mail.gmail.com> When drawing character J alone using font VeraIt.ttf, only some pixels are drawn on the left! The problem looks to be in the font definition of char J. The char is shifted a lot on the left ! Here is the sample. You can try drawing '-J-' and 'J-' from PIL import Image, ImageDraw, ImageFont, ImageTk import PIL border=50 c='J' font=ImageFont.truetype('VeraIt.ttf', 36) x, y=font.getsize(c) print font.getsize(c), font.font.getsize(c) img=Image.new('RGB', (border+x+border, border+y+border), (255, 255, 255)) draw=ImageDraw.Draw(img) draw.rectangle((border, border, x+border-1, y+border-1), outline=(0,0,0), fill=(255, 255, 255)) draw.text( (border, border), c, fill=(0, 0, 0), font=font) del draw img.show(command='gthumb') Best regards. -- Alain Spineux aspineux gmail com May the sources be with you From matt at tplus1.com Fri Feb 16 20:09:52 2007 From: matt at tplus1.com (Matthew Wilson) Date: Fri, 16 Feb 2007 14:09:52 -0500 Subject: [Image-SIG] How to add a frame + caption to another image? Message-ID: I have a bunch of 50x50 PNG files that show a little product. I have some other 50x50 PNG files that are transparent except for the bottom right corner, which has some text like "new!" or "fun!". I figure this is a very straightforward operation, but I'm not getting anywhere yet. Later on, I'd like to dynamically add any arbitrary text to the bottom of the image. I suspect this is straightforward also. All comments welcome. Matt -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.python.org/pipermail/image-sig/attachments/20070216/badd5aa1/attachment.htm From ced at bernispa.com Mon Feb 19 13:12:04 2007 From: ced at bernispa.com (Cesare Leonardi) Date: Mon, 19 Feb 2007 13:12:04 +0100 Subject: [Image-SIG] Problem with TIFF compressed with JPEG Message-ID: <45D99414.6010706@bernispa.com> Hi all. I'd like to know if somobody else can see this problem. I have some TIFF images compressed with JPEG and if i try to convert them to another format (i've tryed with PNG, BMP and JPEG) the colour looks changed. Even if i have reported a similar problem with JPEG CMYK, seems that this is another problem: the colours change in a different way. I've have setup a web page with a sample image composed by the RGB colours and a simple piece of code that trigger the problem. http://www.bernispa.com/pil/index2.html The sample image is generated with Gimp, but i've verified that the problem shows even if the original image is generated with another app (i've tryed with IrfanView). The particular thing is that this conversion happen (from the original image to the converted one): RED become GREEN GREEN become BLUE BLUE become RED BLACK become DARK-GREEN WHITE become MAGENTA And this is independent to the destination format, as can be seen. My system is Windows 2000 Pro SP4, Python 2.5 and PIL 1.1.6 (vanilla). Best regard. Cesare. From dave at leviathangames.com Mon Feb 19 17:35:00 2007 From: dave at leviathangames.com (Dave LeCompte) Date: Mon, 19 Feb 2007 08:35:00 -0800 Subject: [Image-SIG] How to add a frame + caption to another image? References: Message-ID: <000501c75443$e73942a0$3200000a@whale> Matthew Wilson wrote: > Later on, I'd like to dynamically add any arbitrary text to the bottom of > the image. I suspect this is straightforward also. I recently needed to add attributions to a directoryful of images: im=Image.open(fn).convert("RGBA") font=ImageFont.truetype("arial.ttf", 15) sz=font.getsize(att) labelImage=Image.new("RGBA", sz, (0,0,0,0)) labelDraw=ImageDraw.Draw(labelImage) labelDraw.text((0,0),att,fill=(250,250,0), font=font) del labelDraw labelImage=labelImage.rotate(270) # n.b. use the label image's alpha channel as the mask for the paste im.paste(labelImage,(0,0),labelImage) im.save(os.path.join(ATT_DIR,fn)) This code draws text in yellow vertically down the image from the upper left. In my actual script, I position the text a little more pleasingly. The only interesting thing that's going on there is that if you omit the "mask" argument to the "paste" method call: im.paste(labelImage,(0,0)) you end up overwriting the image with transparent pixels, which is probably not what you're interested in. The subject suggests you're also interested in adding a frame around an image - I'd probably do this something like so: framedImage=Image.new("RGB", framedSize, frameColor) framedImage.paste(srcImage, offset) Hope this helps, Dave LeCompte From tim at mail.mew.co.jp Wed Feb 21 07:23:56 2007 From: tim at mail.mew.co.jp (Tim Flink) Date: Wed, 21 Feb 2007 15:23:56 +0900 Subject: [Image-SIG] Garbled Text Message-ID: <45DBE57C.2070502@mail.mew.co.jp> I'm having an issue with garbled fonts and I was hoping that someone might have some suggestions on how to fix them. I'm trying to write some text (both Japanese and Roman characters) using Japanese fonts, but the output is just a random string of lines if I am below a specific size (18 for ipag-mona and 24 for msgothic). I don't seem to have this problem if I print roman characters using a common font (Arial for instance). Nothing seems to change even if I use the "encoding= " with the ImageFont.truetype() constructor. I have included some example code that creates 8 small bitmaps. 4 with Japanese characters using various font sizes and 4 with roman characters using various font sizes. Can anyone see something wrong with my code or have a suggestion for a different way to do this? Thanks, Tim msgothic.ttc comes with the east asian language package for MS Windows (XP at least, I don't know about other versions). ipag-mona.ttf can be downloaded from the following site: http://www.geocities.jp/ipa_mona/ Code was written for Python 2.5 and PIL 1.1.6 (downloaded binary for Win32 and Python2.5) under Windows XP SP2, Japanese Language Edition -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: imageTextIssue.py Url: http://mail.python.org/pipermail/image-sig/attachments/20070221/ce06ef27/attachment.asc From mdriscoll at co.marshall.ia.us Wed Feb 21 15:32:08 2007 From: mdriscoll at co.marshall.ia.us (Mike Driscoll) Date: Wed, 21 Feb 2007 08:32:08 -0600 Subject: [Image-SIG] Scaling polygons dynamically Message-ID: Hi, Our office is working with GIS maps using python and we've hit a snag. Due to the way the GIS software behaves, it will take a land parcel that shares a border with another parcel and call them just one parcel, instead of 2. The land parcels are represented by 2-dimensional polygons. Our solution is to shrink or scale the parcel down by a unit of measurement so that the 2 parcels no longer share a line. Currently we use a Python version of the "inpoly" algorithm listed on this page: http://www.visibone.com/inpoly/. It works great until we hit some of our weird parcels that have 700 vectors. Since we have to move each vector in four directions and then test each vector with the inpoly algorithm, this means that we do 4 X 700 or 2800 calculations. We also have to loop over the number of vectors, so that means 700 X 2800 which takes too long as this is for a web app. Does anyone have an alternate algorithm for this kind of thing? Thank you for any help! Mike Driscoll Applications Specialist MCIS - Technology Center 1 E. Main St. Marshalltown, IA 50158 mdriscoll at co.marshall.ia.us From chris at sunnyneuk.com Wed Feb 21 05:17:06 2007 From: chris at sunnyneuk.com (Chris MacKenzie) Date: Wed, 21 Feb 2007 04:17:06 -0000 Subject: [Image-SIG] Resizing images Message-ID: <08a401c7556f$25deaeb0$0f01a8c0@abi> Hi, I am doing a vast amount of work in photoshop cs2 and then resizing images into multiple sizes for email, web publication, printing out on A3, A4 etc,etc. To date I have been using PhotoShop actions which is a real pain. I have used PIL with python in a programming environment and am aware of the power it gives. My Question is will resizing in PIL reduce the image quality compared to CS2 or will it remain the same as the CS2 output. Thanks in advance Regards & best wishes Chris MacKenzie www.sunnyneuk.com/inspiration www.chris-mackenzie.co.uk -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.python.org/pipermail/image-sig/attachments/20070221/5c79ede9/attachment.htm From newz at bearfruit.org Thu Feb 22 15:58:33 2007 From: newz at bearfruit.org (Matthew Nuzum) Date: Thu, 22 Feb 2007 08:58:33 -0600 Subject: [Image-SIG] Resizing images In-Reply-To: <08a401c7556f$25deaeb0$0f01a8c0@abi> References: <08a401c7556f$25deaeb0$0f01a8c0@abi> Message-ID: On 2/20/07, Chris MacKenzie wrote: > I am doing a vast amount of work in photoshop cs2 and then resizing images > into multiple sizes for email, web publication, printing out on A3, A4 > etc,etc. To date I have been using PhotoShop actions which is a real pain. > My Question is will resizing in PIL reduce the image quality compared to CS2 > or will it remain the same as the CS2 output. I'm not a hard-core pil dev/user, but I've been in the same boat as you, so here's my thoughts: With Photoshop you'll be working from high-res, lossless files (PSDs). If you were to save them out as a high-res jpg and then resize that into smaller files with PIL, you'd definitely loose some quality, since PIL's source material (JPGs) will be of lower quality. If you give PIL a non-lossless format, like 24/32b PNGs and you resize to even multiples of the source image's size (for example, 800x600 --> 400x300 --> 200x150 --> 100x75) I suspect you'd get pretty similar results. Where Photoshop shines, in my experience, is: * resizing to non-even multiple of source image's size (800x600 --> 90x68) * using masks to define different compression ratios for different parts of the image * choosing the best compression ratio to match your desired output size/quality This is just a guess though. Since Photoshop is a proprietary program, no one outside Adobe can be confident about what goes on inside its "save optimized" code. Maybe PIL can do better! Also, different types of photos may be affected differently by the various programs. Line-art may look rotten and photos may look superb. You could batch them and then fix up anything that doesn't look good enough. By the way, I'm surprised you felt using actions a pain... don't you just drop a folder of images onto your action's "droplet" .exe file? I don't use cs2, so maybe they've taken droplets out. -- Matthew Nuzum www.bearfruit.org newz2000 on freenode From newz at bearfruit.org Thu Feb 22 17:45:37 2007 From: newz at bearfruit.org (Matthew Nuzum) Date: Thu, 22 Feb 2007 10:45:37 -0600 Subject: [Image-SIG] Resizing images In-Reply-To: <00d101c7569d$b39725f0$0f01a8c0@abi> References: <08a401c7556f$25deaeb0$0f01a8c0@abi> <00d101c7569d$b39725f0$0f01a8c0@abi> Message-ID: Well, the only way to know for sure is to try it... you could probably whip up a quick and dirty solution in 1-2 hours. And, while I'm sure PIL is as good or better than ImageMagick, different algorithms can sometimes produce different results, so you want to try it out too to see which works best for your art. By the way, I don't know what's going on behind the scenes here, but he obviously uses Python, so maybe PIL too. This is a cool project, though not OSS: http://snipshot.com/ On 2/22/07, Chris MacKenzie wrote: > Hi Mathew, > > Thanks for helping out. Yeah you can do the old droplet thing. > > In my limited experience of CS2, though, I define a new resize action if I > want to modify an existing one. > > Also, I have two sets of actions one for portrait and one for landscape > images to produce the same four constants; A3, A4, Email, Web and I want to > add ebay and Alamay. > > Also, things just seem to get a bit too cluttered for my ordered world. > > It just seems cool and simple in my programmers brain if everything is in a > python script or similar that checks out width > height and uses the correct > sizes. > > Chris > > > ----- Original Message ----- > From: "Matthew Nuzum" > To: "Chris MacKenzie" > Cc: > Sent: Thursday, February 22, 2007 2:58 PM > Subject: Re: [Image-SIG] Resizing images > > > > On 2/20/07, Chris MacKenzie wrote: > >> I am doing a vast amount of work in photoshop cs2 and then resizing > >> images > >> into multiple sizes for email, web publication, printing out on A3, A4 > >> etc,etc. To date I have been using PhotoShop actions which is a real > >> pain. > > > >> My Question is will resizing in PIL reduce the image quality compared to > >> CS2 > >> or will it remain the same as the CS2 output. > > > > I'm not a hard-core pil dev/user, but I've been in the same boat as > > you, so here's my thoughts: > > > > With Photoshop you'll be working from high-res, lossless files (PSDs). > > If you were to save them out as a high-res jpg and then resize that > > into smaller files with PIL, you'd definitely loose some quality, > > since PIL's source material (JPGs) will be of lower quality. > > > > If you give PIL a non-lossless format, like 24/32b PNGs and you resize > > to even multiples of the source image's size (for example, 800x600 --> > > 400x300 --> 200x150 --> 100x75) I suspect you'd get pretty similar > > results. > > > > Where Photoshop shines, in my experience, is: > > * resizing to non-even multiple of source image's size (800x600 --> 90x68) > > * using masks to define different compression ratios for different > > parts of the image > > * choosing the best compression ratio to match your desired output > > size/quality > > > > This is just a guess though. Since Photoshop is a proprietary program, > > no one outside Adobe can be confident about what goes on inside its > > "save optimized" code. Maybe PIL can do better! > > > > Also, different types of photos may be affected differently by the > > various programs. Line-art may look rotten and photos may look superb. > > You could batch them and then fix up anything that doesn't look good > > enough. > > > > By the way, I'm surprised you felt using actions a pain... don't you > > just drop a folder of images onto your action's "droplet" .exe file? I > > don't use cs2, so maybe they've taken droplets out. > > -- > > Matthew Nuzum > > www.bearfruit.org > > newz2000 on freenode > > > > > > -- Matthew Nuzum www.bearfruit.org newz2000 on freenode From lowell at allemansonline.com Thu Feb 22 22:36:37 2007 From: lowell at allemansonline.com (Lowell Alleman) Date: Thu, 22 Feb 2007 16:36:37 -0500 Subject: [Image-SIG] PNG patch for reading zTXt chunks Message-ID: <45DE0CE5.7080501@allemansonline.com> Here is a patch to add support for reading compressed text chunks (zTXt) and storing them in the info dictionary. With this patch, both compressed and uncompressed (tEXt) text chunks can be accessed uniformly. I've come across some text tag discussions on this mailing list from many years ago. Since then, it appears that some support has been added, but not for reading zTXt chunks. Since it has been a while, I'm going to ask that support for reading zTXt chunks be considered again. Previous discussions (patches): http://mail.python.org/pipermail/image-sig/1998-July/000529.html http://mail.python.org/pipermail/image-sig/1999-May/000737.html Here is my patch. I borrowed ideas from the two patches listed above. It should apply cleanly against the 1.1.6 release. diff -Naur Imaging-1.1.6/PIL/PngImagePlugin.py Imaging-LCA/PIL/PngImagePlugin.py --- Imaging-1.1.6/PIL/PngImagePlugin.py 2007-02-21 10:55:03.000000000 -0500 +++ Imaging-LCA/PIL/PngImagePlugin.py 2007-02-21 13:27:15.000000000 -0500 @@ -254,6 +254,19 @@ self.im_info[k] = v return s + def chunk_zTXt(self, pos, len): + s = ImageFile._safe_read(self.fp, len) + (k, v) = string.split(s, "\0", 1) + comp_method = ord(v[0]) + v = v[1:] + if comp_method != 0: + raise SyntaxError, "Unknown compression method %i in zTXt chunk" % comp_method + import zlib + v = zlib.decompress(v) + self.im_info[k] = v + return s + # -------------------------------------------------------------------- # PNG reader Thanks, - Lowell Alleman -------------- next part -------------- A non-text attachment was scrubbed... Name: png_read_zTXt.patch Type: text/x-patch Size: 800 bytes Desc: not available Url : http://mail.python.org/pipermail/image-sig/attachments/20070222/eb571cb7/attachment.bin From jb at langarson.com.au Fri Feb 23 00:07:04 2007 From: jb at langarson.com.au (John Barratt) Date: Fri, 23 Feb 2007 10:07:04 +1100 Subject: [Image-SIG] Resizing images In-Reply-To: <08a401c7556f$25deaeb0$0f01a8c0@abi> References: <08a401c7556f$25deaeb0$0f01a8c0@abi> Message-ID: <45DE2218.6000904@langarson.com.au> Hi Chris, Chris MacKenzie wrote: > I am doing a vast amount of work in photoshop cs2 and then resizing > images into multiple sizes for email, web publication, printing out on > A3, A4 etc,etc. To date I have been using PhotoShop actions which is a > real pain. > > I have used PIL with python in a programming environment and am aware of > the power it gives. > > My Question is will resizing in PIL reduce the image quality compared to > CS2 or will it remain the same as the CS2 output. The main differences (barring bugs/odd implementations) will be the different interpolation methods available to you. Just looking in CS2 the standard ones are : Nearest Neighbour Bilinear Bicubic Bicubic Smoother Bicubic Sharper You can also find a whole lot of discussion on the web about Photoshop actions that given better resizing, in particular 'Stair Interpolation' which is basically changing the size by small amounts and repeating until you reach the desired size. This will take a lot more CPU time, but is meant to give better results. eg http://www.fredmiranda.com/SI/ Looking at PIL and the resize function we have the following methods : NEAREST (use nearest neighbour), BILINEAR (linear interpolation in a 2x2 environment), BICUBIC (cubic spline interpolation in a 4x4 environment), or ANTIALIAS (a high-quality downsampling filter) I would expect that the first three should produce identical results to Photoshop, though there could be some variation to the implementation of the algorithm in some methods. You could confirm this and otherwise see how the other versions from the two compare. The main thing might be that python/PIL is perhaps a bit slower, but if you don't have too many images, or they aren't too big, and can easily script it to take less of your time, then you should win out on time. If desired you should be able to replicate the Stair Interpolation method within PIL fairly easily, I have done before, but can't find the code right now. A separate note on getting the best out of resizing for email/web is that it is a good idea to sharpen the image with an unsharp mask after it has been resized. This makes a very marked difference to the end result. If you have a search for "resize image unsharp" on google to find some further discussion. Here is one : http://www.cambridgeincolour.com/tutorials/image-resize-for-web.htm This leaves PIL at a little bit of a disadvantage as there isn't a default unsharp mask in PIL, but there was a plugin/patch built for it! It was for an older version, but I think I had it working ok with at least 1.1.4, and probably wouldn't take much to get to work with 1.1.6 if it didn't work as is : See : http://www.cazabon.com/pyCMS/PIL_usm.html Hope this helps, JB. From douglas at paradise.net.nz Fri Feb 23 00:57:16 2007 From: douglas at paradise.net.nz (Douglas Bagnall) Date: Fri, 23 Feb 2007 12:57:16 +1300 Subject: [Image-SIG] Resizing images In-Reply-To: <45DE2218.6000904@langarson.com.au> References: <08a401c7556f$25deaeb0$0f01a8c0@abi> <45DE2218.6000904@langarson.com.au> Message-ID: <45DE2DDC.70800@paradise.net.nz> Chris MacKenzie wrote: >> My Question is will resizing in PIL reduce the image quality compared to >> CS2 or will it remain the same as the CS2 output. I don't know about Photoshop, but this thread http://mail.python.org/pipermail/image-sig/2005-May/003310.html will tell you that this function: def stretch(im, size, filter=Image.NEAREST): im.load() im = im._new(im.im.stretch(size, filter)) return im gives pixel-identical results to the Gimp's best resize method, if you use PIL 1.1.6. With 1.1.5, the results might be offset by half a pixel, but you won't notice that unless you are making very small images. If you don't actually need identical results, but are happy enough with something that looks fine, then im.resize(size, Image.ANTIALIAS) should work. John Barratt wrote: > Looking at PIL and the resize function we have the following methods : > > NEAREST (use nearest neighbour), > BILINEAR (linear interpolation in a 2x2 environment), > BICUBIC (cubic spline interpolation in a 4x4 environment), or > ANTIALIAS (a high-quality downsampling filter) > > I would expect that the first three should produce identical results to > Photoshop, though there could be some variation to the implementation of > the algorithm in some methods. Actually this isn't the case -- apart from ANTIALIAS, the PIL resize modes are bad at downsampling. douglas From cewing at u.washington.edu Fri Feb 23 00:13:00 2007 From: cewing at u.washington.edu (cristopher pierson ewing) Date: Thu, 22 Feb 2007 15:13:00 -0800 (PST) Subject: [Image-SIG] problems with selftest on OS X intel XServe Message-ID: Hi all, I'm trying to build PIL to include it in python for support of a zope/plone installation. All my tests so far have been on a dev machine with the pre-built binaries, which include PIL. Now I'm working on my server, a new Intel XServe box running OS X 10.4.8. I'm working with a compiled installation of Python 2.4.4, built earlier today from source. Running $ python2.4 setup.py build_ext -i works just fine, I get all the expected output, including the information that support for my required features is okay: -------------------------------------------------------------------- PIL 1.1.6 BUILD SUMMARY -------------------------------------------------------------------- version 1.1.6 platform darwin 2.4.4 (#1, Feb 22 2007, 10:42:01) [GCC 4.0.1 (Apple Computer, Inc. build 5367)] -------------------------------------------------------------------- --- TKINTER support ok --- JPEG support ok --- ZLIB (PNG/ZIP) support ok --- FREETYPE2 support ok -------------------------------------------------------------------- Great! So I run selftest.py and it fails with the following output: ***************************************************************** Failure in example: _info(Image.open("Images/lena.jpg")) from line #24 of selftest.testimage Exception raised: Traceback (most recent call last): File "./doctest.py", line 499, in _run_examples_inner exec compile(source, "", "single") in globs File "", line 1, in ? File "./selftest.py", line 22, in _info im.load() File "PIL/ImageFile.py", line 180, in load d = Image._getdecoder(self.mode, d, a, self.decoderconfig) File "PIL/Image.py", line 375, in _getdecoder raise IOError("decoder %s not available" % decoder_name) IOError: decoder jpeg not available 1 items had failures: 1 of 57 in selftest.testimage ***Test Failed*** 1 failures. *** 1 tests of 57 failed. Now, from that I can see that somehow the jpeg decoder is not getting found despite the fact that build_ext says that jpeg support is present. I've been searching on this list over the last few hours, and found some posts that suggested running python -vv -c "_imaging" to verify that the imaging module was in the python being used, and doing so showed that it was not. However, this seems to be a chicken-or-egg thing. How can python have the imaging module available without me installing it? And how can I install it if it fails this test? I tried anyway to install, that worked fine, running `python -vv . . .` showed that it was in fact being imported from the expected place, but selftest fails in exactly the same way, every time. Only one other thing I've noticed that might have some bearing on the situation: When I first run `python2.4 setup.py build_ext -i`, there is a line at the very top of the output that says: running build_ext --- using frameworks at /System/Library/Frameworks OS X has a standard, built-in python in the Frameworks that is version 2.3.5. I can't use it for zope/plone since I need 2.4, but I wonder if setup.py is somehow getting confused about which python to use?? 'python2.4' in the above command is a link to the executable of my self-built python 2.4.4, and that's the one I want PIL to be available to. Any help would be greatly appreciated. Sorry if there is a solution out there that I've missed in my searching. 'My eyes are growing weary . . .' Thanks Cris ******************************** Cris Ewing CME and Telehealth Web Services Department of Radiology Web Services University of Washington School of Medicine Work Phone: (206) 685-9116 Home Phone: (206) 365-3413 E-mail: cewing at u.washington.edu ******************************* From Chris.Barker at noaa.gov Fri Feb 23 20:31:14 2007 From: Chris.Barker at noaa.gov (Christopher Barker) Date: Fri, 23 Feb 2007 11:31:14 -0800 Subject: [Image-SIG] problems with selftest on OS X intel XServe In-Reply-To: References: Message-ID: <45DF4102.1040104@noaa.gov> Is there a reason you can't use these?: http://pythonmac.org/packages/py24-fat/index.html It would be a whole lot easier. I do see that there is not a 1.1.6 build of PIL there. If you need 1.1.6, I'd try to built it with that Python, and if you have trouble, the folks on the pythonmac list will be helpful. If you do get it built, it wold be great to submit it to that archive, too. If you really need to build your own Python, you may want to do a framework build. It's a configure incantation that I don't' know off the top of my head. -Chris cristopher pierson ewing wrote: > Hi all, > > I'm trying to build PIL to include it in python > Now I'm working on my > server, a new Intel XServe box running OS X 10.4.8. > > I'm working with a compiled installation of Python 2.4.4, built earlier > today from source. -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov From Chris.Barker at noaa.gov Sat Feb 24 00:21:11 2007 From: Chris.Barker at noaa.gov (Christopher Barker) Date: Fri, 23 Feb 2007 15:21:11 -0800 Subject: [Image-SIG] problems with selftest on OS X intel XServe In-Reply-To: References: <45DF4102.1040104@noaa.gov> Message-ID: <45DF76E7.6010907@noaa.gov> cristopher pierson ewing wrote: > The only reason I haven't done a framework build is to avoid killing the > original python that comes on the box. Just in case there's anything > else that uses it that I'm forgetting. You're right that you don't want to kill the one there, but it's a 2.3 version, and adding a 2.4 version will not kill it, they can live quite happily together. I've got Apple's 2.3 build, and both 2.4 and 2.5 I installed myself-- all Framework builds. > I wasn't aware of those packages. I'll check it out. And be sure to check out/join the pythonmac list. Very helpful folks. http://mail.python.org/mailman/listinfo/pythonmac-sig -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov From cewing at u.washington.edu Sat Feb 24 00:13:49 2007 From: cewing at u.washington.edu (cristopher pierson ewing) Date: Fri, 23 Feb 2007 15:13:49 -0800 (PST) Subject: [Image-SIG] problems with selftest on OS X intel XServe In-Reply-To: <45DF4102.1040104@noaa.gov> References: <45DF4102.1040104@noaa.gov> Message-ID: The only reason I haven't done a framework build is to avoid killing the original python that comes on the box. Just in case there's anything else that uses it that I'm forgetting. I wasn't aware of those packages. I'll check it out. I don't know that I need PIL1.1.6, so maybe an earlier build will work. I just like building every piece from source so I know what I've got running in all cases. C ******************************** Cris Ewing CME and Telehealth Web Services Department of Radiology Web Services University of Washington School of Medicine Work Phone: (206) 685-9116 Home Phone: (206) 365-3413 E-mail: cewing at u.washington.edu ******************************* On Fri, 23 Feb 2007, Christopher Barker wrote: > Is there a reason you can't use these?: > > http://pythonmac.org/packages/py24-fat/index.html > > It would be a whole lot easier. I do see that there is not a 1.1.6 build of > PIL there. If you need 1.1.6, I'd try to built it with that Python, and if > you have trouble, the folks on the pythonmac list will be helpful. If you do > get it built, it wold be great to submit it to that archive, too. > > If you really need to build your own Python, you may want to do a framework > build. It's a configure incantation that I don't' know off the top of my > head. > > -Chris > > > cristopher pierson ewing wrote: >> Hi all, >> >> I'm trying to build PIL to include it in python > >> Now I'm working on my server, a new Intel XServe box running OS X 10.4.8. >> >> I'm working with a compiled installation of Python 2.4.4, built earlier >> today from source. > > > -- > Christopher Barker, Ph.D. > Oceanographer > > Emergency Response Division > NOAA/NOS/OR&R (206) 526-6959 voice > 7600 Sand Point Way NE (206) 526-6329 fax > Seattle, WA 98115 (206) 526-6317 main reception > > Chris.Barker at noaa.gov > From blake at phantomfiber.com Mon Feb 26 18:00:41 2007 From: blake at phantomfiber.com (Blake Winton) Date: Mon, 26 Feb 2007 12:00:41 -0500 Subject: [Image-SIG] Small addition to the IcoImagePlugin. Message-ID: I've been using PIL to verify some images, and one of the things I wanted to verify was that icon files contained a certain number of sizes in specific bit-depths. The included IcoImagePlugin only reads out the information for the largest bit depth, which wasn't so useful for me, so I added the following two lines, which set the info['bmp_sizes'] to a list of tuples of (width, height, bitdepth). Anyways, I thought someone else out there might find it useful, so here it is. Thanks, Blake. Diff follows: *** IcoImagePlugin.py.orig Mon Feb 26 11:51:06 2007 --- IcoImagePlugin.py Mon Feb 26 11:27:43 2007 *************** *** 54,65 **** --- 54,67 ---- # pick the largest icon in the file m = "" + self.info['bmp_sizes'] = [] for i in range(i16(s[4:])): s = self.fp.read(16) if not m: m = s elif ord(s[0]) > ord(m[0]) and ord(s[1]) > ord(m[1]): m = s + self.info['bmp_sizes'].append( (ord(s[0]), ord(s[1]), i16(s[6:])) ) #print "width", ord(s[0]) #print "height", ord(s[1]) #print "colors", ord(s[2]) From tianqig at gmail.com Mon Feb 26 11:51:14 2007 From: tianqig at gmail.com (qi tian) Date: Mon, 26 Feb 2007 18:51:14 +0800 Subject: [Image-SIG] Error in im.show() - The _imaging C module is not installed Message-ID: <3c29ca5e0702260251q6996e968v779077bd03c7da19@mail.gmail.com> Hi, I tried to use the Python Imaging Library, can read in images, and print formats, size, modes. But when I tried to use im.show() to display the images, I got the above message. So far I have installed Python 2.5 and PIL 1.1.6 on a pc with XP, do I need to install other modules? Can someone help? Thanks Tian -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.python.org/pipermail/image-sig/attachments/20070226/b582d1e0/attachment.htm From fredrik at pythonware.com Tue Feb 27 14:02:08 2007 From: fredrik at pythonware.com (Fredrik Lundh) Date: Tue, 27 Feb 2007 14:02:08 +0100 Subject: [Image-SIG] Error in im.show() - The _imaging C module is notinstalled References: <3c29ca5e0702260251q6996e968v779077bd03c7da19@mail.gmail.com> Message-ID: "qi tian" wrote: > I tried to use the Python Imaging Library, can read in images, > and print formats, size, modes. But when I tried to use > im.show() to display the images, I got the above message. > > So far I have installed Python 2.5 and PIL 1.1.6 on a pc with XP, > do I need to install other modules? your installation is broken (which is a bit odd if you used the standard binary installers). here's some troubleshooting advice: http://effbot.org/zone/pil-imaging-not-installed.htm (hint: this is the first google hit for the given error message...) From skomoroh at gmail.com Tue Feb 27 17:35:42 2007 From: skomoroh at gmail.com (Con Radchenko) Date: Tue, 27 Feb 2007 19:35:42 +0300 Subject: [Image-SIG] Patch: alpha-channel support for ImageTk Message-ID: A non-text attachment was scrubbed... Name: imagetk-alpha.patch Type: text/x-patch Size: 1636 bytes Desc: not available Url : http://mail.python.org/pipermail/image-sig/attachments/20070227/c09f650f/attachment.bin From tianqig at gmail.com Wed Feb 28 03:22:09 2007 From: tianqig at gmail.com (qi tian) Date: Wed, 28 Feb 2007 10:22:09 +0800 Subject: [Image-SIG] Error in im.show() - The _imaging C module is notinstalled In-Reply-To: References: <3c29ca5e0702260251q6996e968v779077bd03c7da19@mail.gmail.com> Message-ID: <3c29ca5e0702271822v51921210scf03289a9f9b8d2a@mail.gmail.com> Thanks, the page is very useful. Follow the instruction, then I reinstalled everything, now it works. BTW, I tried to install the Pymorph Morphology Toolbox V0.8, somehow, it could not find the modules at all. See the url at http://www.mmorph.com/pymorph/ Wonder if you have any suggestions? Thanks Tian On 2/27/07, Fredrik Lundh wrote: > > "qi tian" wrote: > > > I tried to use the Python Imaging Library, can read in images, > > and print formats, size, modes. But when I tried to use > > im.show() to display the images, I got the above message. > > > > So far I have installed Python 2.5 and PIL 1.1.6 on a pc with XP, > > do I need to install other modules? > > your installation is broken (which is a bit odd if you used the standard > binary installers). here's some troubleshooting advice: > > http://effbot.org/zone/pil-imaging-not-installed.htm > > (hint: this is the first google hit for the given error message...) > > > > > > _______________________________________________ > Image-SIG maillist - Image-SIG at python.org > http://mail.python.org/mailman/listinfo/image-sig > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.python.org/pipermail/image-sig/attachments/20070228/65590709/attachment.htm From irgendetwas at charlie.at Wed Feb 28 17:47:08 2007 From: irgendetwas at charlie.at (Charlie) Date: Wed, 28 Feb 2007 17:47:08 +0100 Subject: [Image-SIG] kinda patch for better iptc keyword support in PIL Message-ID: <1172681228.29187.15.camel@webmail.charlie.at> Hi having just started in python I naturally started writing my own image gallery program. what else ;-) Trying to minimise the dependencies I started using the iptc support in PIL, but ran into a 'bug' in the keyword retrieval. iptc allows multile keyword entries and the PIL iptc handler only stores the last entry it sees. By making changes in PIL IptcImagePlugin.py class IptcImageFile _open I now get a comma separated list (works for me, but is not standard conform) Code changes were only between the two comments. I am sure that there are better ways of doing this in python, unfortunately I do not know them (yet). # load descriptive fields t225 = '' try: while 1: offset = self.fp.tell() tag, size = self.field() if not tag or tag == (8,10): break if size: if tag != (2,25): self.info[tag] = self.fp.read(size) else: if t225 != '': t225 += ',' t225 += str(self.fp.read(size)) else: self.info[tag] = None print tag #, self.info[tag] except (IndexError, KeyError): pass # expected failure if t225 != '': print 't225', t225 self.info[(2, 25)] = t225 # mode regards charlie