From gherman@darwin.in-berlin.de Sun Jan 5 01:06:36 2003 From: gherman@darwin.in-berlin.de (Dinu Gherman) Date: Sun, 5 Jan 2003 02:06:36 +0100 Subject: [Image-SIG] Fixes for PIL enhancers In-Reply-To: <3DFEB8AE.1080407@onsitetech.com> Message-ID: Robb Shecter: > I having seen postings on this, so I thought I'd ask: > The ImageEnhance module in PIL 1.1.3 is pretty rough For example, > most functions don't implement the full API (ie. being able to > desaturate but not oversaturate colors in an image). > > So I've implemented them all. :-) Was this wasted work? Has it been > fixed up yet? I can't see it on the changes list from 1.1.3 to 1.1.4, so I'd be interested in your patches. (I just found that ImageEnhance.Brightness(img).enhance(f) would not intensify an image for f > 1, but only dim it down for 0 <= f < 1... Dinu -- Dinu C. Gherman ...................................................................... Make your own Bush speech: http://www.lemonbovril.co.uk/bushspeech From gherman@darwin.in-berlin.de Tue Jan 7 15:55:23 2003 From: gherman@darwin.in-berlin.de (Dinu Gherman) Date: Tue, 7 Jan 2003 16:55:23 +0100 Subject: [Image-SIG] Fixes for PIL enhancers In-Reply-To: <3E1A13E0.4010307@onsitetech.com> Message-ID: <6E6E68CC-2258-11D7-8FB8-00039345C610@darwin.in-berlin.de> [Sent this before erroneously to Robb and the Pythonmac list... :-/] Robb Shecter: > Any suggestions (or more Enhancer implementations!) are appreciated. Well, I was experimenting with automated enhancers for photographs and played a bit with the effects of shifting an image's histogram by some constant offset. (The code below works, but I'm not sure if this is fully PIL-mantra-compliant?! ;-) The existing Brightness enhancer is different since it multiplies pixel values by a factor and the histogram changes its width slight- ly. I reckon that it is probably hopeless to try one's hands on fully automated brightness/contrast enhancement of photographs without some AI component... But maybe I should try some non-linear ver- sions, too, before saaying that... class Shift(ImageEnhance._Enhance): "An enhancer that shifts the histogram of an image by some offset." def __init__(self, im): self.im =3D im def enhance(self, offset): return self.im.point(lambda i: i+offset) Regards, Dinu -- Dinu C. Gherman ...................................................................... "La perfection est atteinte, non pas lorsqu'il n'y a plus rien =E0 ajouter, mais lorsqu'il n'y a plus rien =E0 retirer." (Antoine de Saint-Exup=E9ry) From fredrik@pythonware.com Tue Jan 7 21:23:39 2003 From: fredrik@pythonware.com (Fredrik Lundh) Date: Tue, 7 Jan 2003 22:23:39 +0100 Subject: [Image-SIG] Fixes for PIL enhancers References: Message-ID: <011e01c2b693$0db86030$ced241d5@hagrid> Dinu Gherman wrote: > I can't see it on the changes list from 1.1.3 to 1.1.4, > so I'd be interested in your patches. (I just found that > ImageEnhance.Brightness(img).enhance(f) would not intensify > an image for f > 1, but only dim it down for 0 <= f < 1... the bug is in Image.blend, not in the ImageEnhance module. despite what the documentation says, the "blend" function only works properly for alpha values between 0.0 and 1.0 (I have no idea when this was changed). the fix is straightforward: ==== //modules/pil/PIL/Image.py *** 1530,1539 **** def blend(im1, im2, alpha): "Interpolate between images." - if alpha <= 0.0: - return im1 - elif alpha >= 1.0: - return im2 im1.load() im2.load() return im1._new(core.blend(im1.im, im2.im, alpha)) --- 1530,1535 ---- From rs@onsitetech.com Mon Jan 6 23:40:16 2003 From: rs@onsitetech.com (Robb Shecter) Date: Mon, 06 Jan 2003 15:40:16 -0800 Subject: [Image-SIG] Fixes for PIL enhancers References: Message-ID: <3E1A13E0.4010307@onsitetech.com> This is a multi-part message in MIME format. --------------090100070507030306020803 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Dinu Gherman wrote: > ...I just found that ImageEnhance.Brightness(img).enhance(f) would not > intensify > an image for f > 1, but only dim it down for 0 <= f < 1... Yep! That's what got me started. Here's what I've come up with. It's working in a production app, too. It has a lot features for introspection and meta-data in order to be able to support flexible use like this: http://wiki.wxpython.org/index.cgi/RobbShecter?action=AttachFile&do=view&target=image-editor.jpg I also have dialogs, for example, that automatically build themselves with appropriately created sliders for all Enhancers that accept an integer parameter. Any suggestions (or more Enhancer implementations!) are appreciated. Robb --------------090100070507030306020803 Content-Type: text/plain; name="Enhance.py" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="Enhance.py" # # ui.image.Enhance # import Image, ImageFilter, ImageChops class ScaleTranslator(object): """ A class that translates linearly between two scales. It works by treating the start points as a 2D point and the end points as a 2D point. It then solves the equation for the line that connects these points (y = mx + b). This line, then, becomes the mapping from one scale to another; every (x,y) pair along it is effectively a mapping from (oldscale,newscale). Here's how this class is used: say you have a wxSlider which gives values from 1 to 25. But you want these converted to work with a library that expects values between -1 and 1: >>> st = ScaleTranslator(1, 25, -1, 1) To find the translated equivalent of a number like 6, you'd do: >>> st.translate(6) -0.58333333333333326 """ def __init__(self, scale1Start, scale1End, scale2Start, scale2End): """ Instantiate a ScaleTranslator that converts from scale 1 to scale 2. """ # Solve the equation by calculating m and b. x1 = scale1Start y1 = scale2Start x2 = scale1End y2 = scale2End self.__m = (float(y2) - y1) / (x2 - x1) self.__b = y1 - (self.__m * x1) def translate(self, aNumber): """ Return the equivalent of aNumber in the new scale. Do it by calculating (y = mx + b), where aNumber is x.""" return self.__m * aNumber + self.__b class Enhancer(object): """ An abstract base class for PIL image enhancers. """ __scale = ScaleTranslator(-100,100,-1,1) def __init__(self, pilImage): self.__mode = pilImage.mode if self.__mode != 'RGB': self.__image = pilImage.convert('RGB') else: self.__image = pilImage self.__lastValue = 0 self.__less = None self.__more = None # # Public API # def getValue(self): """ Return the enhancement value of the image produced by the last call to enhance(). """ return self.__lastValue def enhance(self, value): """ value is in the range [-100,100]. """ newImage = self.__enhance(value) # Commented out, because this conversion is not # done very well. #if newImage.mode != self.__mode: # newImage = newImage.convert(self.__mode) return newImage # # Metadata API # def getInfo(): """ Return information about the currently imported enhancers. This returns a dict of dicts, initially keyed on the human-readable name for each enhancer. """ if not hasattr(Enhancer, 'metadata'): subclasses = Enhancer.__subclasses__() info = {} for aClass in subclasses: info[aClass.getName()] = {'class': aClass, 'domain': aClass.getDomain()} Enhancer.metadata = info return Enhancer.metadata def getEnhancers(domain): """ Return a list of enhancers that accept values in the given domain. This will match domains specified either as a general or specific domain. (More docs coming.) """ info = Enhancer.getInfo() if len(domain) == 1: l = filter(lambda i: i[1]['domain'][0] == domain[0], info.items()) else: l = filter(lambda i: i[1]['domain'] == domain, info.items()) return dict(l) getInfo = staticmethod(getInfo) getEnhancers = staticmethod(getEnhancers) def __enhance(self, value): from util.Math import limitToRange self.__lastValue = value # 1. See if the rawEnhance protocol has # been implemented: if hasattr(self, 'rawEnhance'): return self.rawEnhance(self.__image, value) # 2. Continue on with the more complex protocol: domain = self.__class__.domain if domain[0] == int: min = domain[1][0] max = domain[1][1] if value != limitToRange(value, min, max): raise ValueError('enhancement value not within [%d, %d]' % (min, max)) if value == 0 and (min == -1 * max): # Zero means no change return self.__image # To do: Make customized scale translator if necessary. alpha = self.__class__.__scale.translate(value) if alpha < 0: alpha *= -1 if self.__less is None: # Lazily instantiate self.__less = self.makeDecreasingDegenerate(self.__image) degenerate = self.__less else: if self.__more is None: # Lazily instantiate self.__more = self.makeIncreasingDegenerate(self.__image) degenerate = self.__more return Image.blend(self.__image, degenerate, alpha) # # Class methods # domain = (int, (-100,100)) def getDomain(myClass): """ Return a tuple containing the type of the value that's required, plus a way of specifying its legal values. """ return myClass.domain def getName(myClass): """ Return my human-readable name. """ return myClass.name getDomain = classmethod(getDomain) getName = classmethod(getName) # # Template methods to be implemented by subclasses # def makeDecreasingDegenerate(self, aPilImage): """ Implemented by subclasses to provide an image that REDUCES the effect when mixed with the original. """ raise NotImplementedError('Enhancer is an abstract class') def makeIncreasingDegenerate(self, aPilImage): """ Implemented by subclasses to provide an image that INCREASES the effect when mixed with the original. """ raise NotImplementedError('Enhancer is an abstract class') # # Support some standard protocols. # def Destroy(self): self.__less = None self.__more = None class ResizeEnhancer(Enhancer): name = 'Resize Image' domain = (tuple,) def rawEnhance(self, image, newSize): return image.resize(newSize, Image.ANTIALIAS) class ShrinkToFitEnhancer(Enhancer): name = 'Shrink To Fit' domain = (tuple,) def rawEnhance(self, image, newSize): # Image.thumbnail() makes changes in place: newImage = image.copy() newImage.thumbnail(newSize, Image.ANTIALIAS) return newImage class CanvasSizeEnhancer(Enhancer): # To do: implement for reducing the canvas size. name = 'Resize Canvas' domain = (tuple,) def rawEnhance(self, image, (newSize, bgColor)): w, h = newSize W, H = image.size if w 128 and 255) class BrightnessEnhancer(Enhancer): """ An enhancer that changes the brightness level of a PIL image. """ name = 'Brightness' def makeDecreasingDegenerate(self, image): return Image.new(image.mode, image.size, (0,0,0)) def makeIncreasingDegenerate(self, image): return Image.new(image.mode, image.size, (255,255,255)) class SharpnessEnhancer(Enhancer): name = 'Sharpness' def makeDecreasingDegenerate(self, image): return image.filter(ImageFilter.SMOOTH_MORE) def makeIncreasingDegenerate(self, image): return image.filter(ImageFilter.SHARPEN) class ColorEnhancer(Enhancer): name = 'Color Saturation' def makeDecreasingDegenerate(self, image): return image.convert("L").convert(image.mode) def makeIncreasingDegenerate(self, image): # # The formula for my algorithm is: # Overcolored = Image - (alpha * Grey) / (1 - alpha) # alpha = 0.7 grey = self.makeDecreasingDegenerate(image) alpha_g = grey.point(lambda x: x * alpha) i_minus_alpha_g = ImageChops.subtract(image, alpha_g) overcolored = i_minus_alpha_g.point(lambda x: x / (1-alpha)) return overcolored if __name__ == '__main__': from pprint import * desc = """This module has classes that make up a framework for manipulating PIL (Python Image Library) images. It could be changed, though, to work with any images. These are the current enhancer types that are available:""" pprint (desc) pprint (Enhancer.getInfo()) --------------090100070507030306020803-- From mhammond@skippinet.com.au Tue Jan 7 01:51:08 2003 From: mhammond@skippinet.com.au (Mark Hammond) Date: Tue, 7 Jan 2003 12:51:08 +1100 Subject: [Image-SIG] (no subject) Message-ID: <012701c2b5ef$40127d80$530f8490@eden> This is a multi-part message in MIME format. ------=_NextPart_000_0128_01C2B64B.7382F580 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit I made a few changes to the 1.1.3 setup.py file. This new version seems to work "out-of-the-box" for me, including automatically building the libImaging directory. It should allow someone to unzip the tar file, and have setup.py do absolutely everything necessary. Let me know if this is still any use to the development version, which I don't have access to. The PIL pages indicate patches should be sent here, but I am not subscribed, so please CC me on any replies. Thanks, Mark. ------=_NextPart_000_0128_01C2B64B.7382F580 Content-Type: application/octet-stream; name="setup.py.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="setup.py.patch" --- \temp\setup.py 2002-03-15 06:55:04.000000000 +1100=0A= +++ setup.py 2003-01-07 12:31:06.000000000 +1100=0A= @@ -22,10 +22,28 @@=0A= HOMEPAGE =3D "http://www.pythonware.com/products/pil" =20 # on windows, the build script expects to find both library files and -# include files in the directories below. tweak as necessary. -JPEGDIR =3D "../../kits/jpeg-6b" -ZLIBDIR =3D "../../kits/zlib-1.1.3" - +# include files in one of the directories below. tweak as necessary. +kit_dirs =3D ["../../kits", ".."] +# All kit_dirs will be searched for a sub-directory as specified. +tool_dirs =3D [ + ("ZLIBDIR", ("zlib-1.1.4","zlib-1.1.3")), + ("JPEGDIR", ("jpeg-6b", "jpeg-6a")), +] + +for var_name, look_dirs in tool_dirs: + for kit_dir in kit_dirs: + found =3D 0 + for look_dir in look_dirs: + look =3D os.path.abspath(os.path.join(kit_dir, look_dir)) + if os.path.isdir(look): + globals()[var_name] =3D look + print "set '%s=3D%s'" % (var_name, look) + found =3D 1 + break + if not found: + print "Can not configure '%s' - please tweak %s" \ + % (var_name, os.path.basename(sys.argv[0])) + =20 # on windows, the following is used to control how and where to search # for Tcl/Tk files. None enables automatic searching; to override, set # this to a directory name @@ -48,6 +66,27 @@=0A= HAVE_LIBTIFF =3D 0 HAVE_LIBZ =3D 0 =20 +# If on Windows, we make a feeble attempt at shelling out to +# build the library if it doesn't exist. +if sys.platform =3D=3D "win32" and \ + not os.path.isfile(os.path.join("libImaging", "Imaging.lib")): + print "Can't find the PIL Imaging library - trying to build it!" + # virgin install's need a .h file copied. + if not os.path.isfile(os.path.join("libImaging", "ImConfig.h")): + shutil.copyfile( os.path.join("libImaging", "ImConfig.h.win"), \ + os.path.join("libImaging", "ImConfig.h")) + command =3D 'nmake -f makefile.win JPEGINCLUDE=3D"-I%s" = ZLIBINCLUDE=3D"-I%s"' \ + % (JPEGDIR, ZLIBDIR) + cwd =3D os.getcwd() + try: + os.chdir("libImaging") + rc =3D os.system(command) + if rc: + print "*** Build of PIL Imaging library failed" + sys.exit(rc) + finally: + os.chdir(cwd) + # parse ImConfig.h to figure out what external libraries we're using for line in open(os.path.join("libImaging", "ImConfig.h")).readlines(): m =3D re.match("#define\s+HAVE_LIB([A-Z]+)", line) @@ -56,7 +95,7 @@=0A= if lib =3D=3D "JPEG": HAVE_LIBJPEG =3D 1 if sys.platform =3D=3D "win32": - LIBRARIES.append("jpeg") + LIBRARIES.append("libjpeg") INCLUDE_DIRS.append(JPEGDIR) LIBRARY_DIRS.append(JPEGDIR) else: ------=_NextPart_000_0128_01C2B64B.7382F580-- From fredrik@pythonware.com Tue Jan 7 07:48:19 2003 From: fredrik@pythonware.com (Fredrik Lundh) Date: Tue, 7 Jan 2003 08:48:19 +0100 Subject: [Image-SIG] Fixes for PIL enhancers References: Message-ID: <004b01c2b621$28bd5d30$ced241d5@hagrid> Dinu Gherman wrote: > I can't see it on the changes list from 1.1.3 to 1.1.4, > so I'd be interested in your patches. (I just found that > ImageEnhance.Brightness(img).enhance(f) would not intensify > an image for f > 1, but only dim it down for 0 <= f < 1... the bug is in Image.blend, not in the ImageEnhance module. despite what the documentation says, the "blend" function only works properly for alpha values between 0.0 and 1.0 (I have no idea when this was changed). the fix is straightforward: ==== //modules/pil/PIL/Image.py *** 1530,1539 **** def blend(im1, im2, alpha): "Interpolate between images." - if alpha <= 0.0: - return im1 - elif alpha >= 1.0: - return im2 im1.load() im2.load() return im1._new(core.blend(im1.im, im2.im, alpha)) --- 1530,1535 ---- From esr@snark.thyrsus.com Thu Jan 9 11:03:38 2003 From: esr@snark.thyrsus.com (Eric S. Raymond) Date: Thu, 9 Jan 2003 06:03:38 -0500 Subject: [Image-SIG] Pasting images Message-ID: <200301091103.h09B3cTi016333@snark.thyrsus.com> I'm confused by the behavior of the paste() method. I'm trying to paste a PNG image onto a background generated by Image,new(). It appears to me from the manual that if flag.png is a 30x30 image, the following sequence of operations im = Image.new("P", (60, 60)) flag = Image.open("flag.png") im.paste(flag, (15, 15)) ought to leave the flag pasted onto the middle of a black background. It doesn't. All I see is black. PIL 1.1.3, Python 2.3a0, Red Hat 8.0. While we're att it, how do I generate a new image that is transparent? Or set a transparency color on an existing image? Setting the 'transparency' memeber of an image's info dict doesn't seem to do it. What am I doing wrong? -- Eric S. Raymond As with the Christian religion, the worst advertisement for Socialism is its adherents. -- George Orwell From robmyroon@yahoo.com Thu Jan 9 19:32:04 2003 From: robmyroon@yahoo.com (Rob Myroon) Date: Thu, 9 Jan 2003 11:32:04 -0800 (PST) Subject: [Image-SIG] Pasting images In-Reply-To: <200301091103.h09B3cTi016333@snark.thyrsus.com> Message-ID: <20030109193204.62613.qmail@web11402.mail.yahoo.com> I recently had similar transparency problems with .png files ... In order to save a .png with transparency I modified PngImagePlugin.py. I added these lines starting at line 427 in function _save() if im.mode == "P": chunk(fp, "PLTE", im.im.getpalette("RGB")) # extra code starts here (this is line 427) if not im.encoderinfo.has_key("transparency"): if im.info.has_key("transparency"): im.encoderinfo["transparency"] = im.info["transparency"] # extra code ends here if im.encoderinfo.has_key("transparency"): if im.mode == "P": This works for .pngs with mode "P". I didn't test it for mode "L". Just make sure the 'transparency' member of the image's info dict is set. Rob --- "Eric S. Raymond" wrote: > I'm confused by the behavior of the paste() method. I'm trying to > paste a PNG image onto a background generated by Image,new(). > > It appears to me from the manual that if flag.png is a 30x30 image, > the following sequence of operations > > im = Image.new("P", (60, 60)) > flag = Image.open("flag.png") > im.paste(flag, (15, 15)) > > ought to leave the flag pasted onto the middle of a black background. > > It doesn't. All I see is black. > > PIL 1.1.3, Python 2.3a0, Red Hat 8.0. > > While we're att it, how do I generate a new image that is transparent? > Or set a transparency color on an existing image? Setting the > 'transparency' memeber of an image's info dict doesn't seem to do it. > > What am I doing wrong? > -- > Eric S. Raymond > > As with the Christian religion, the worst advertisement for Socialism > is its adherents. > -- George Orwell > > _______________________________________________ > Image-SIG maillist - Image-SIG@python.org > http://mail.python.org/mailman/listinfo/image-sig __________________________________________________ Do you Yahoo!? Yahoo! Mail Plus - Powerful. Affordable. Sign up now. http://mailplus.yahoo.com From webmaster@pferdemarkt.ws Wed Jan 15 12:26:01 2003 From: webmaster@pferdemarkt.ws (webmaster@pferdemarkt.ws) Date: Wed, 15 Jan 2003 04:26:01 -0800 Subject: [Image-SIG] Pferdemarkt.ws informiert! Newsletter 01/2003 Message-ID: <200301151226.EAA02900@eagle.he.net> http://www.pferdemarkt.ws Wir sind in 2003 erfolgreich in des neue \"Pferdejahr 2003 gestartet. Für den schnellen Erfolg unseres Marktes möchten wir uns bei Ihnen bedanken. Heute am 15. Januar 2003 sind wir genau 14 Tage Online! Täglich wächst unsere Datenbank um ca. 30 neue Angebote. Stellen auch Sie als Privatperson Ihre zu verkaufenden Pferde direkt und vollkommen Kostenlos ins Internet. Zur besseren Sichtbarmachung Ihrer Angebote können SIe bis zu ein Bild zu Ihrer Pferdeanzeige kostenlos einstellen! Klicken Sie hier um sich direkt einzuloggen http://www.Pferdemarkt.ws Kostenlos Anbieten, Kostenlos Suchen! Direkt von Privat zu Privat! Haben Sie noch Fragen mailto: webmaster@pferdemarkt.ws From frank.derville@wanadoo.fr Thu Jan 16 21:46:53 2003 From: frank.derville@wanadoo.fr (Frank Derville) Date: Thu, 16 Jan 2003 22:46:53 +0100 Subject: [Image-SIG] TrueType support in PIL 1.1.4 a1 Message-ID: <000c01c2bda8$cb128860$44c6fea9@Hal> I have been a long time user of PIL and I appreciate it very much. I use = it for auto labelling of pictures and make town maps (http://art-nouveau.kubos.org/en/index.htm). The new truetype support is great but it seems to be broken with special characte= rs like =E9,=E8,=FC, © .... they appear as squares in PIL although in m= y favourite word processor they are OK with the same tt font. Another (but aesthetic problem) is that when displaying a sentence, PIL sometimes hide some parts on the left of some chars, as if in the text display algorythm, the chars were written one by one, backwards, and not with a transparent background (whi= ch seems to me is the problem). Am I wrong? Hope this helps to improve PIL. Regards Frank From fredrik@pythonware.com Fri Jan 17 09:00:59 2003 From: fredrik@pythonware.com (Fredrik Lundh) Date: Fri, 17 Jan 2003 10:00:59 +0100 Subject: [Image-SIG] TrueType support in PIL 1.1.4 a1 References: <000c01c2bda8$cb128860$44c6fea9@Hal> Message-ID: <008801c2be06$f722a800$ced241d5@hagrid> frank wrote: > I have been a long time user of PIL and I appreciate it very much. I us= e it > for auto labelling of pictures and make town maps > (http://art-nouveau.kubos.org/en/index.htm). The new > truetype support is great but it seems to be broken with special charac= ters > like =E9,=E8,=FC, © .... they appear as squares in PIL although in= my > favourite word processor they are OK with the same tt font. the version in 1.1.4a1 messes up on non-ascii characters. the following patch fixes this, and adds support for unicode strings as well. regards /F =3D=3D=3D=3D //modules/pil/_imagingft.c#4 (ktext) - //modules/pil/_imagin= gft.c#7 (ktext) =3D=3D=3D=3D content *************** *** 7,18 **** * history: * 2001-02-17 fl Created (based on old experimental freetype 1.0 code) * 2001-04-18 fl Fixed some egcs compiler nits * * Copyright (c) 1998-2001 by Secret Labs AB */ - /* FIXME: add unicode support (1.6 and later) */ - #include "Python.h" #include "Imaging.h" --- 7,17 ---- * history: * 2001-02-17 fl Created (based on old experimental freetype 1.0 code) * 2001-04-18 fl Fixed some egcs compiler nits + * 2002-11-08 fl Added unicode support; more font metrics, etc * * Copyright (c) 1998-2001 by Secret Labs AB */ #include "Python.h" #include "Imaging.h" *************** *** 82,105 **** return (PyObject*) self; } static PyObject* font_getsize(FontObject* self, PyObject* args) { int i, x; /* calculate size for a given string */ ! char* text; ! int chars; ! if (!PyArg_ParseTuple(args, "s#", &text, &chars)) return NULL; #if PY_VERSION_HEX >=3D 0x01060000 ! /* FIXME: Unicode support */ #endif ! for (x =3D i =3D 0; i < chars; i++) { int index, error; ! index =3D FT_Get_Char_Index(self->face, (FT_ULong) text[i]); error =3D FT_Load_Glyph(self->face, index, FT_LOAD_DEFAULT); if (error) goto failure; --- 81,134 ---- return (PyObject*) self; } + static int + font_getchar(PyObject* string, int index, FT_ULong* char_out) + { + #if PY_VERSION_HEX >=3D 0x01060000 + if (PyUnicode_Check(string)) { + Py_UNICODE* p =3D PyUnicode_AS_UNICODE(string); + int size =3D PyUnicode_GET_SIZE(string); + if (index >=3D size) + return 0; + *char_out =3D p[index]; + return 1; + } else + #endif + if (PyString_Check(string)) { + unsigned char* p =3D PyString_AS_STRING(string); + int size =3D PyString_GET_SIZE(string); + if (index >=3D size) + return 0; + *char_out =3D (unsigned char) p[index]; + return 1; + } + return 0; + } + static PyObject* font_getsize(FontObject* self, PyObject* args) { int i, x; + FT_ULong ch; /* calculate size for a given string */ ! ! PyObject* string; ! if (!PyArg_ParseTuple(args, "O:getsize", &string)) return NULL; #if PY_VERSION_HEX >=3D 0x01060000 ! if (!PyUnicode_Check(string) && !PyString_Check(string)) { ! #else ! if (!PyString_Check(string)) { #endif + PyErr_SetString(PyExc_TypeError, "expected string"); + return NULL; + } ! for (x =3D i =3D 0; font_getchar(string, i, &ch); i++) { int index, error; ! index =3D FT_Get_Char_Index(self->face, ch); error =3D FT_Load_Glyph(self->face, index, FT_LOAD_DEFAULT); if (error) goto failure; *************** *** 123,146 **** Imaging im; int index, error, ascender; unsigned char *source; FT_GlyphSlot glyph; /* render string into given buffer (the buffer *must* have the right size, or this will crash) */ ! char* text; ! int chars; long id; ! if (!PyArg_ParseTuple(args, "s#l", &text, &chars, &id)) return NULL; #if PY_VERSION_HEX >=3D 0x01060000 ! /* FIXME: Unicode support */ #endif im =3D (Imaging) id; ! for (x =3D i =3D 0; i < chars; i++) { ! index =3D FT_Get_Char_Index(self->face, (FT_ULong) text[i]); error =3D FT_Load_Glyph(self->face, index, FT_LOAD_RENDER); if (error) goto failure; --- 152,180 ---- Imaging im; int index, error, ascender; unsigned char *source; + FT_ULong ch; FT_GlyphSlot glyph; /* render string into given buffer (the buffer *must* have the right size, or this will crash) */ ! PyObject* string; long id; ! if (!PyArg_ParseTuple(args, "Ol:render", &string, &id)) return NULL; #if PY_VERSION_HEX >=3D 0x01060000 ! if (!PyUnicode_Check(string) && !PyString_Check(string)) { ! #else ! if (!PyString_Check(string)) { #endif + PyErr_SetString(PyExc_TypeError, "expected string"); + return NULL; + } im =3D (Imaging) id; ! for (x =3D i =3D 0; font_getchar(string, i, &ch); i++) { ! index =3D FT_Get_Char_Index(self->face, ch); error =3D FT_Load_Glyph(self->face, index, FT_LOAD_RENDER); if (error) goto failure; *************** *** 198,210 **** /* attributes */ if (!strcmp(name, "family")) ! return Py_BuildValue("s", self->face->family_name); if (!strcmp(name, "style")) ! return Py_BuildValue("s", self->face->style_name); if (!strcmp(name, "glyphs")) /* number of glyphs provided by this font */ ! return Py_BuildValue("i", self->face->num_glyphs); PyErr_SetString(PyExc_AttributeError, name); return NULL; --- 232,249 ---- /* attributes */ if (!strcmp(name, "family")) ! return PyString_FromString(self->face->family_name); if (!strcmp(name, "style")) ! return PyString_FromString(self->face->style_name); ! ! if (!strcmp(name, "ascent")) ! return PyInt_FromLong(PIXEL(self->face->size->metrics.ascender)= ); ! if (!strcmp(name, "descent")) ! return PyInt_FromLong(-PIXEL(self->face->size->metrics.descende= r)); if (!strcmp(name, "glyphs")) /* number of glyphs provided by this font */ ! return PyInt_FromLong(self->face->num_glyphs); PyErr_SetString(PyExc_AttributeError, name); return NULL; From vivsar_guve@yahoo.co.uk Wed Jan 22 15:11:04 2003 From: vivsar_guve@yahoo.co.uk (Vivek Kumar) Date: Wed, 22 Jan 2003 07:11:04 -0800 (PST) Subject: [Image-SIG] Unable to build from source on cygwin ( PIL 1.1.3) Message-ID: <20030122151104.32625.qmail@web11403.mail.yahoo.com> hi all, I am trying to install the PIL 1.1.3 on cygwin(windows 98) using source distribution. It makes the files properly in the libimaging directory. But when i try to run python setup.py build then it fails with the following error message running build_ext building '_imaging' extension gcc -DNDEBUG -g -O3 -Wall -Wstrict-prototypes -DUSE_CL_IMPORT -IlibImaging -I/usr/include -I/usr/include -I/usr/include/python2.2 -c _imaging.c -o build/temp.cygwin-1.3.18-i386-2.2/_imaging.o C:\CYGWIN\BIN\PYTHON2.2.EXE: *** couldn't allocate memory 0x10000(4128768) for 'c:\CYGWIN\BIN\CYGZ.DLL' alignment, Win32 error 8 103 [main] python 21583 sync_with_child: child -335743(0xE0) died before initialization with status code 0x1 610 [main] python 21583 sync_with_child: *** child state child loading dlls error: resource temporarily unavailable Can anyone help me, Pleaseeee Thanking in advance Vivek Kumar __________________________________________________ Do you Yahoo!? Yahoo! Mail Plus - Powerful. Affordable. Sign up now. http://mailplus.yahoo.com From rtrocca@libero.it Thu Jan 23 12:38:11 2003 From: rtrocca@libero.it (=?iso-8859-1?Q?rtrocca@libero.it?=) Date: Thu, 23 Jan 2003 13:38:11 +0100 Subject: [Image-SIG] =?iso-8859-1?Q?A_library_to_access_AVI, _QuickTime_and_webcams_in_python/pygame?= Message-ID: Hello, I'd like to announce that I released a library (win32 only) for py= thon called pyVideoIO that allows to read AVI, QuickTime and input from a= webcam (and several image formats) and use it in pygame or PIL. The soft= ware is not tested so much but it seems to work. I already used it (toget= her with some other extensions that are not quite ready for public releas= e) during a live performance to create videoFx in realtime on a video pro= jector. Pygame allowed me to do it in a few hours (it was an emergency). = The software can be used to play video (even from a webcam) in realtime i= n a pygame window. I was able to use it even with a wxPython window.=0D=0A= The installer will create a doc and example folders in the same directory= where the lib resides (python22/Lib/site-packages/pyVideoIO).=0D=0AI'll = soon release the source code (The fact is that the building process is a = mess by now and I have to create a website too). Anyway the library is LG= PL. It uses FreeImage in order to handle different image formats. I hope = that this ad interim release will work on your PC. It has been tested on = Win2k and WinXP. It uses VFW to open AVI files. QuickTime must be install= ed in order to use the QuickTime movie reader.=0D=0AFuture releases will = include a better documentation, source code, bug fixes and the possibilit= y to write AVI files from python. I hope I'll have time (or someone else = will do it) to add an AVIReader that uses DirectShow and to improve Quick= Time handling. It would be cool to be able to have a simple QT API for Py= thon and use it for batch processing. It is already possible to implement= a simple tool that takes a movie and saves every frame a single image (p= ng, jpg, bmp tiff).=0D=0AIt is also possible to convert frames to PIL ima= ges.=0D=0A=0D=0AWell, enough. The link is:=0D=0A=0D=0Ahttp://spazioinwind= .libero.it/rtrocca/files/pyVideoIO-1.0.win32-py2.2.exe=0D=0A=0D=0Asorry f= or the lack of a better web site, but I'll make it asap.=0D=0APlease send= me some feedback, ideas, hints.=0D=0AIf somebody wants to share its expe= rience with DistUtils it would be welcome.=0D=0A=0D=0ARiccardo Trocca=0D=0A= rtrocca@inwind.it=0D=0A=0D=0A From ehagemann@comcast.net Sat Jan 25 02:43:11 2003 From: ehagemann@comcast.net (eric hagemann) Date: Fri, 24 Jan 2003 21:43:11 -0500 Subject: [Image-SIG] help building PIL1.1.3 on WIn32 Message-ID: <000501c2c41b$80881c00$6401a8c0@eric> Hello, Trying to use PIL 1.1.3 on Python2.2.2 under windows 2K When I build using setup.py, there is a problem finding the TCL/TK libraries Seems that setup.py is looking for tk.h -- no such file in the python distribution. I then downloaded the python2.2.2 source distribution and did not find it there either. What's the best way to perform the build -- from setup.py it looks like I can point the imaging module to a separate installation of tcl/tk, however I would assume that I need to have that version match the version that was used to compile python. Any help would be appreciated Cheers Eric From fredrik@pythonware.com Sat Jan 25 17:44:10 2003 From: fredrik@pythonware.com (Fredrik Lundh) Date: Sat, 25 Jan 2003 18:44:10 +0100 Subject: [Image-SIG] help building PIL1.1.3 on WIn32 References: <000501c2c41b$80881c00$6401a8c0@eric> Message-ID: <002b01c2c499$603b88f0$ced241d5@hagrid> eric hagemann wrote: > When I build using setup.py, there is a problem finding the TCL/TK > libraries > > Seems that setup.py is looking for tk.h -- no such file in the python > distribution. I then downloaded the python2.2.2 source distribution and did > not find it there either. tk.h is part of the Tcl/Tk source distribution (http://www.tcl.tk/) > What's the best way to perform the build -- from setup.py it looks like > I can point the imaging module to a separate installation of tcl/tk, however > I would assume that I need to have that version match the version that was > used to compile python. correct. or if you don't need tkinter support, you can disable the Tkinter check in setup.py (the easiest way is replace the "import _tkinter" line with "raise ImportError"). From kevin@cazabon.com Sat Jan 25 23:52:07 2003 From: kevin@cazabon.com (Kevin@Cazabon.com) Date: Sat, 25 Jan 2003 16:52:07 -0700 Subject: [Image-SIG] Unsharp Masking and Gaussian Blur for PIL References: <000501c2c41b$80881c00$6401a8c0@eric> <002b01c2c499$603b88f0$ced241d5@hagrid> Message-ID: <000701c2c4cc$c4e91fa0$310aa8c0@duallie> Hey everyone; I've written a DLL for PIL that does proper Gaussian Blur and Unsharp Masking (sharpening). It's pretty quick, and the results are a LOT more pleasing, powerful and configurable than the standard sharpen/blur functions in PIL. It's currently released under LGPL in the stand-alone form. A zip of the C++ source, Python wrapper module, and a pre-built Windows binary is available from: http://www.cazabon.com/pyCMS/downloads/PIL_usm_0.1.0.zip FRED: if you're willing to put this in the core PIL library (I hope so!), let me know and I'll gladly send you a license-less version (as long as you maintain my contact info in the code of course). The functions work for RGB, RGBA, RGBX, and CMYK, mode images only (It is supposed to support L mode too, but I have some work to do there still, probably in version 0.2.0). If you've ever used Gaussian Blur or Unsharp Masking in Photoshop, this works EXACTLY the same way. I'll write up a short explanation for those that haven't and post it soon. If you use the .py wrapper module, it's pretty simple: ########## import Image import PIL_usm a = Image.open("c:\\temp\\test.tif") b = PIL_usm.gblur(a, radius = 5) # gaussian blur function c = PIL_usm.usm(a, radius = 5, percent = 150, threshold = 3) # unsharp masking function b.save("c:\\temp\\test_blur.tif") c.save("c:\\temp\\test_sharpen.tif") ########## Enjoy! Kevin. From kevin@cazabon.com Sun Jan 26 03:51:18 2003 From: kevin@cazabon.com (Kevin@Cazabon.com) Date: Sat, 25 Jan 2003 20:51:18 -0700 Subject: [Image-SIG] Unsharp Masking and Gaussian Blur for PIL References: <000501c2c41b$80881c00$6401a8c0@eric> <002b01c2c499$603b88f0$ced241d5@hagrid> <000701c2c4cc$c4e91fa0$310aa8c0@duallie> Message-ID: <003c01c2c4ee$2ee02fe0$310aa8c0@duallie> Small update, version 0.2.0, sorry! L mode images now work properly as well. http://www.cazabon.com/pyCMS/downloads/PIL_usm_0.2.0.zip Kevin. > ########## > > import Image > import PIL_usm > > a = Image.open("c:\\temp\\test.tif") > b = PIL_usm.gblur(a, radius = 5) # gaussian blur function > c = PIL_usm.usm(a, radius = 5, percent = 150, threshold = 3) # unsharp > masking function > > b.save("c:\\temp\\test_blur.tif") > c.save("c:\\temp\\test_sharpen.tif") > > ########## From kevin@cazabon.com Sun Jan 26 18:13:46 2003 From: kevin@cazabon.com (Kevin@Cazabon.com) Date: Sun, 26 Jan 2003 11:13:46 -0700 Subject: [Image-SIG] Unsharp Masking and Gaussian Blur for PIL References: <000501c2c41b$80881c00$6401a8c0@eric> <002b01c2c499$603b88f0$ced241d5@hagrid> <000701c2c4cc$c4e91fa0$310aa8c0@duallie> <003c01c2c4ee$2ee02fe0$310aa8c0@duallie> Message-ID: <001901c2c566$aac2e2b0$310aa8c0@duallie> Just so I don't KEEP bothering everyone, I've set up a home page for PIL_usm for now. Version 0.3.0 is posted with some speed and functionality improvements (and slightly better C++ coding). Last post here for new versions, I promise. q:] Here's the home page for those that are interested. http://www.cazabon.com/pyCMS/PIL_usm.html Kevin. From geddert@arche.ag Mon Jan 27 11:33:15 2003 From: geddert@arche.ag (Michael Geddert) Date: Mon, 27 Jan 2003 12:33:15 +0100 Subject: [Image-SIG] PIL patch for non-ascii characters in TTF Message-ID: <3E3518FB.20306@arche.ag> Hi all, Has anybody accomplished to get fully functional truetype-support for non-ascii characters in PIL with Fredrik's recent patch ? Somehow I can't get the sources patched properly - I'd just like to know that it's possible and that it's working (I'm especially concerned about german umlauts and the like). Regards, Michael