Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeshav Sharma <keshav7890@gmail.com>2011-07-06 18:54:41 (GMT)
committer Keshav Sharma <keshav7890@gmail.com>2011-07-06 18:54:41 (GMT)
commitff9e8108a9912e60e8d341272c443590eaadb890 (patch)
tree6fbbcb667816d92bc5f6e84c63afe78946451609
parent17a7dee95319f511fcd82cd93e6b09ed3c02923c (diff)
added changes in all files
-rw-r--r--AUTHORS12
-rw-r--r--ImageProcess.py61
-rw-r--r--ImageProcessorActivity.py24
-rw-r--r--Imaging/BUILDME6
-rw-r--r--Imaging/CHANGES1547
-rw-r--r--Imaging/CONTENTS295
-rw-r--r--Imaging/Docs/effbot.css118
-rw-r--r--Imaging/Docs/index.html103
-rw-r--r--Imaging/Docs/pythondoc-PIL.ArgImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.BdfFontFile.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.BmpImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.BufrStubImagePlugin.html20
-rw-r--r--Imaging/Docs/pythondoc-PIL.ContainerIO.html87
-rw-r--r--Imaging/Docs/pythondoc-PIL.CurImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.DcxImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.EpsImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.ExifTags.html19
-rw-r--r--Imaging/Docs/pythondoc-PIL.FitsStubImagePlugin.html20
-rw-r--r--Imaging/Docs/pythondoc-PIL.FliImagePlugin.html25
-rw-r--r--Imaging/Docs/pythondoc-PIL.FontFile.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.FpxImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.GbrImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.GdImageFile.html43
-rw-r--r--Imaging/Docs/pythondoc-PIL.GifImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.GimpGradientFile.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.GimpPaletteFile.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.GribStubImagePlugin.html20
-rw-r--r--Imaging/Docs/pythondoc-PIL.Hdf5StubImagePlugin.html20
-rw-r--r--Imaging/Docs/pythondoc-PIL.IcnsImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.IcoImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.Image.html931
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImageChops.html282
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImageColor.html25
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImageDraw.html111
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImageEnhance.html77
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImageFile.html117
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImageFileIO.html43
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImageFilter.html257
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImageFont.html141
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImageGL.html24
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImageGrab.html37
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImageOps.html221
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImagePalette.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImagePath.html54
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImageSequence.html32
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImageStat.html37
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImageTk.html141
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImageTransform.html140
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImageWin.html141
-rw-r--r--Imaging/Docs/pythondoc-PIL.ImtImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.IptcImagePlugin.html36
-rw-r--r--Imaging/Docs/pythondoc-PIL.JpegImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.McIdasImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.MicImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.MpegImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.MspImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.OleFileIO.html39
-rw-r--r--Imaging/Docs/pythondoc-PIL.PSDraw.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.PaletteFile.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.PalmImagePlugin.html16
-rw-r--r--Imaging/Docs/pythondoc-PIL.PcdImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.PcfFontFile.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.PcxImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.PdfImagePlugin.html16
-rw-r--r--Imaging/Docs/pythondoc-PIL.PixarImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.PngImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.PpmImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.PsdImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.SgiImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.SpiderImagePlugin.html28
-rw-r--r--Imaging/Docs/pythondoc-PIL.SunImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.TarIO.html35
-rw-r--r--Imaging/Docs/pythondoc-PIL.TgaImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.TiffImagePlugin.html34
-rw-r--r--Imaging/Docs/pythondoc-PIL.TiffTags.html19
-rw-r--r--Imaging/Docs/pythondoc-PIL.WalImageFile.html28
-rw-r--r--Imaging/Docs/pythondoc-PIL.WmfImagePlugin.html31
-rw-r--r--Imaging/Docs/pythondoc-PIL.XVThumbImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.XbmImagePlugin.html23
-rw-r--r--Imaging/Docs/pythondoc-PIL.XpmImagePlugin.html23
-rw-r--r--Imaging/Images/courB08.bdf2676
-rw-r--r--Imaging/Images/courB08.pbmbin0 -> 1273 bytes
-rw-r--r--Imaging/Images/courB08.pilbin0 -> 5143 bytes
-rw-r--r--Imaging/Images/lena.gifbin0 -> 16336 bytes
-rw-r--r--Imaging/Images/lena.jpgbin0 -> 4788 bytes
-rw-r--r--Imaging/Images/lena.ppm4
-rw-r--r--Imaging/MANIFEST275
-rw-r--r--Imaging/PIL.pth1
-rw-r--r--Imaging/PIL/ArgImagePlugin.py498
-rw-r--r--Imaging/PIL/BdfFontFile.py133
-rw-r--r--Imaging/PIL/BmpImagePlugin.py245
-rw-r--r--Imaging/PIL/BufrStubImagePlugin.py68
-rw-r--r--Imaging/PIL/ContainerIO.py116
-rw-r--r--Imaging/PIL/CurImagePlugin.py90
-rw-r--r--Imaging/PIL/DcxImagePlugin.py78
-rw-r--r--Imaging/PIL/EpsImagePlugin.py349
-rw-r--r--Imaging/PIL/ExifTags.py157
-rw-r--r--Imaging/PIL/FitsStubImagePlugin.py73
-rw-r--r--Imaging/PIL/FliImagePlugin.py142
-rw-r--r--Imaging/PIL/FontFile.py146
-rw-r--r--Imaging/PIL/FpxImagePlugin.py226
-rw-r--r--Imaging/PIL/GbrImagePlugin.py70
-rw-r--r--Imaging/PIL/GdImageFile.py86
-rw-r--r--Imaging/PIL/GifImagePlugin.py405
-rw-r--r--Imaging/PIL/GimpGradientFile.py124
-rw-r--r--Imaging/PIL/GimpPaletteFile.py61
-rw-r--r--Imaging/PIL/GribStubImagePlugin.py68
-rw-r--r--Imaging/PIL/Hdf5StubImagePlugin.py70
-rw-r--r--Imaging/PIL/IcnsImagePlugin.py211
-rw-r--r--Imaging/PIL/IcoImagePlugin.py88
-rw-r--r--Imaging/PIL/ImImagePlugin.py335
-rw-r--r--Imaging/PIL/Image.py2093
-rw-r--r--Imaging/PIL/ImageChops.py302
-rw-r--r--Imaging/PIL/ImageColor.py262
-rw-r--r--Imaging/PIL/ImageDraw.py378
-rw-r--r--Imaging/PIL/ImageDraw2.py108
-rw-r--r--Imaging/PIL/ImageEnhance.py89
-rw-r--r--Imaging/PIL/ImageFile.py520
-rw-r--r--Imaging/PIL/ImageFileIO.py47
-rw-r--r--Imaging/PIL/ImageFilter.py263
-rw-r--r--Imaging/PIL/ImageFont.py377
-rw-r--r--Imaging/PIL/ImageGL.py28
-rw-r--r--Imaging/PIL/ImageGrab.py71
-rw-r--r--Imaging/PIL/ImageMath.py207
-rw-r--r--Imaging/PIL/ImageMode.py46
-rw-r--r--Imaging/PIL/ImageOps.py408
-rw-r--r--Imaging/PIL/ImagePalette.py161
-rw-r--r--Imaging/PIL/ImagePath.py71
-rw-r--r--Imaging/PIL/ImageQt.py84
-rw-r--r--Imaging/PIL/ImageSequence.py38
-rw-r--r--Imaging/PIL/ImageStat.py179
-rw-r--r--Imaging/PIL/ImageTk.py296
-rw-r--r--Imaging/PIL/ImageTransform.py91
-rw-r--r--Imaging/PIL/ImageWin.py215
-rw-r--r--Imaging/PIL/ImtImagePlugin.py93
-rw-r--r--Imaging/PIL/IptcImagePlugin.py280
-rw-r--r--Imaging/PIL/JpegImagePlugin.py430
-rw-r--r--Imaging/PIL/McIdasImagePlugin.py74
-rw-r--r--Imaging/PIL/MicImagePlugin.py96
-rw-r--r--Imaging/PIL/MpegImagePlugin.py83
-rw-r--r--Imaging/PIL/MspImagePlugin.py103
-rw-r--r--Imaging/PIL/OleFileIO.py528
-rw-r--r--Imaging/PIL/PSDraw.py199
-rw-r--r--Imaging/PIL/PaletteFile.py53
-rw-r--r--Imaging/PIL/PalmImagePlugin.py226
-rw-r--r--Imaging/PIL/PcdImagePlugin.py76
-rw-r--r--Imaging/PIL/PcfFontFile.py256
-rw-r--r--Imaging/PIL/PcxImagePlugin.py167
-rw-r--r--Imaging/PIL/PdfImagePlugin.py210
-rw-r--r--Imaging/PIL/PixarImagePlugin.py71
-rw-r--r--Imaging/PIL/PngImagePlugin.py558
-rw-r--r--Imaging/PIL/PpmImagePlugin.py131
-rw-r--r--Imaging/PIL/PsdImagePlugin.py271
-rw-r--r--Imaging/PIL/SgiImagePlugin.py91
-rw-r--r--Imaging/PIL/SpiderImagePlugin.py294
-rw-r--r--Imaging/PIL/SunImagePlugin.py87
-rw-r--r--Imaging/PIL/TarIO.py57
-rw-r--r--Imaging/PIL/TgaImagePlugin.py133
-rw-r--r--Imaging/PIL/TiffImagePlugin.py763
-rw-r--r--Imaging/PIL/TiffTags.py200
-rw-r--r--Imaging/PIL/WalImageFile.py125
-rw-r--r--Imaging/PIL/WmfImagePlugin.py148
-rw-r--r--Imaging/PIL/XVThumbImagePlugin.py68
-rw-r--r--Imaging/PIL/XbmImagePlugin.py94
-rw-r--r--Imaging/PIL/XpmImagePlugin.py129
-rw-r--r--Imaging/PIL/__init__.py12
-rw-r--r--Imaging/README270
-rw-r--r--Imaging/Sane/CHANGES34
-rw-r--r--Imaging/Sane/README22
-rw-r--r--Imaging/Sane/_sane.c1325
-rw-r--r--Imaging/Sane/demo_numarray.py39
-rw-r--r--Imaging/Sane/demo_pil.py33
-rw-r--r--Imaging/Sane/sane.py289
-rw-r--r--Imaging/Sane/sanedoc.txt294
-rw-r--r--Imaging/Sane/setup.py24
-rw-r--r--Imaging/Scripts/README83
-rw-r--r--Imaging/Scripts/enhancer.py53
-rw-r--r--Imaging/Scripts/explode.py107
-rw-r--r--Imaging/Scripts/gifmaker.py135
-rw-r--r--Imaging/Scripts/image2py.py125
-rw-r--r--Imaging/Scripts/painter.py72
-rw-r--r--Imaging/Scripts/pilconvert.py96
-rw-r--r--Imaging/Scripts/pildriver.py523
-rw-r--r--Imaging/Scripts/pilfile.py94
-rw-r--r--Imaging/Scripts/pilfont.py54
-rw-r--r--Imaging/Scripts/pilprint.py93
-rw-r--r--Imaging/Scripts/player.py121
-rw-r--r--Imaging/Scripts/thresholder.py68
-rw-r--r--Imaging/Scripts/viewer.py46
-rw-r--r--Imaging/Tk/booster.txt108
-rw-r--r--Imaging/Tk/install.txt41
-rw-r--r--Imaging/Tk/pilbitmap.txt149
-rw-r--r--Imaging/Tk/tkImaging.c247
-rw-r--r--Imaging/_imaging.c3149
-rw-r--r--Imaging/_imagingft.c463
-rw-r--r--Imaging/_imagingmath.c256
-rw-r--r--Imaging/_imagingtk.c71
-rw-r--r--Imaging/decode.c689
-rw-r--r--Imaging/display.c731
-rw-r--r--Imaging/doctest.py1111
-rw-r--r--Imaging/encode.c531
-rw-r--r--Imaging/libImaging/Access.c63
-rw-r--r--Imaging/libImaging/Antialias.c307
-rw-r--r--Imaging/libImaging/Bands.c129
-rw-r--r--Imaging/libImaging/Bit.h30
-rw-r--r--Imaging/libImaging/BitDecode.c138
-rw-r--r--Imaging/libImaging/Blend.c79
-rw-r--r--Imaging/libImaging/Chops.c148
-rw-r--r--Imaging/libImaging/Convert.c1080
-rw-r--r--Imaging/libImaging/ConvertYCbCr.c387
-rw-r--r--Imaging/libImaging/Copy.c58
-rw-r--r--Imaging/libImaging/Crc32.c87
-rw-r--r--Imaging/libImaging/Crop.c57
-rw-r--r--Imaging/libImaging/Dib.c311
-rw-r--r--Imaging/libImaging/Draw.c1167
-rw-r--r--Imaging/libImaging/Effects.c370
-rw-r--r--Imaging/libImaging/EpsEncode.c80
-rw-r--r--Imaging/libImaging/Except.c78
-rw-r--r--Imaging/libImaging/File.c198
-rw-r--r--Imaging/libImaging/Fill.c89
-rw-r--r--Imaging/libImaging/Filter.c176
-rw-r--r--Imaging/libImaging/FliDecode.c205
-rw-r--r--Imaging/libImaging/Geometry.c957
-rw-r--r--Imaging/libImaging/GetBBox.c322
-rw-r--r--Imaging/libImaging/Gif.h109
-rw-r--r--Imaging/libImaging/GifDecode.c297
-rw-r--r--Imaging/libImaging/GifEncode.c319
-rw-r--r--Imaging/libImaging/HexDecode.c67
-rw-r--r--Imaging/libImaging/Histo.c169
-rw-r--r--Imaging/libImaging/ImDib.h64
-rw-r--r--Imaging/libImaging/ImPlatform.h72
-rw-r--r--Imaging/libImaging/Imaging.h495
-rw-r--r--Imaging/libImaging/Jpeg.h96
-rw-r--r--Imaging/libImaging/JpegDecode.c266
-rw-r--r--Imaging/libImaging/JpegEncode.c211
-rw-r--r--Imaging/libImaging/Lzw.h52
-rw-r--r--Imaging/libImaging/LzwDecode.c230
-rw-r--r--Imaging/libImaging/Matrix.c74
-rw-r--r--Imaging/libImaging/ModeFilter.c78
-rw-r--r--Imaging/libImaging/MspDecode.c91
-rw-r--r--Imaging/libImaging/Negative.c42
-rw-r--r--Imaging/libImaging/Offset.c61
-rw-r--r--Imaging/libImaging/Pack.c531
-rw-r--r--Imaging/libImaging/PackDecode.c92
-rw-r--r--Imaging/libImaging/Palette.c316
-rw-r--r--Imaging/libImaging/Paste.c555
-rw-r--r--Imaging/libImaging/PcdDecode.c78
-rw-r--r--Imaging/libImaging/PcxDecode.c75
-rw-r--r--Imaging/libImaging/PcxEncode.c148
-rw-r--r--Imaging/libImaging/Point.c263
-rw-r--r--Imaging/libImaging/Quant.c1606
-rw-r--r--Imaging/libImaging/Quant.h40
-rw-r--r--Imaging/libImaging/QuantDefines.h25
-rw-r--r--Imaging/libImaging/QuantHash.c473
-rw-r--r--Imaging/libImaging/QuantHash.h36
-rw-r--r--Imaging/libImaging/QuantHeap.c150
-rw-r--r--Imaging/libImaging/QuantHeap.h23
-rw-r--r--Imaging/libImaging/QuantTypes.h28
-rw-r--r--Imaging/libImaging/RankFilter.c105
-rw-r--r--Imaging/libImaging/Raw.h15
-rw-r--r--Imaging/libImaging/RawDecode.c89
-rw-r--r--Imaging/libImaging/RawEncode.c89
-rw-r--r--Imaging/libImaging/Storage.c399
-rw-r--r--Imaging/libImaging/SunRleDecode.c112
-rw-r--r--Imaging/libImaging/TgaRleDecode.c118
-rw-r--r--Imaging/libImaging/Unpack.c1027
-rw-r--r--Imaging/libImaging/UnpackYCC.c162
-rw-r--r--Imaging/libImaging/XbmDecode.c81
-rw-r--r--Imaging/libImaging/XbmEncode.c106
-rw-r--r--Imaging/libImaging/Zip.h53
-rw-r--r--Imaging/libImaging/ZipDecode.c208
-rw-r--r--Imaging/libImaging/ZipEncode.c314
-rw-r--r--Imaging/map.c382
-rw-r--r--Imaging/outline.c180
-rw-r--r--Imaging/path.c585
-rw-r--r--Imaging/selftest.py161
-rw-r--r--Imaging/setup.py457
-rw-r--r--MANIFEST512
-rw-r--r--activity/activity-imageprocessor.svg45
-rw-r--r--activity/activity.info13
-rw-r--r--activity/activity.info.rtfbin0 -> 520 bytes
-rw-r--r--dist/ImageProcessor-4.xobin0 -> 667819 bytes
-rw-r--r--icons/blur.svg256
-rw-r--r--icons/contour.svg313
-rw-r--r--icons/embross.svg486
-rw-r--r--icons/finedges.svg265
-rw-r--r--icons/grey.svg172
-rw-r--r--icons/invert.svg481
-rw-r--r--icons/left_bottom.svg412
-rw-r--r--icons/left_top.svg435
-rw-r--r--icons/mirror.svg251
-rw-r--r--icons/offset.svg349
-rw-r--r--icons/original.svg127
-rw-r--r--icons/right_bottom.svg428
-rw-r--r--icons/right_top.svg440
-rw-r--r--icons/sharpen.svg402
-rw-r--r--icons/solarize.svg104
-rw-r--r--setup.py16
-rw-r--r--toolbar.py65
300 files changed, 58897 insertions, 2211 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..bf4dfb3
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,12 @@
+Contributors
+============
+Keshav Sharma <keshav7890@gmail.com>
+Vaibhav Sharma
+
+Original author
+---------------
+Keshav Sharma <keshav7890@gmail.com>
+
+Maintainers
+-----------
+Vaibhav Sharma
diff --git a/ImageProcess.py b/ImageProcess.py
index 2e5cb54..26506a5 100644
--- a/ImageProcess.py
+++ b/ImageProcess.py
@@ -21,7 +21,7 @@ import gtk
from gtk import gdk
import gobject
import sys
-import Image,ImageEnhance,ImageFont,ImageFilter,ImageOps
+from PIL import Image,ImageEnhance,ImageFont,ImageFilter,ImageOps
import ImageDraw
import StringIO
import logging
@@ -47,6 +47,9 @@ class ImageProcessor(gtk.DrawingArea):
def __init__(self):
gtk.DrawingArea.__init__(self)
self.set_app_paintable(True)
+ self.undo = None
+ self.redo = None
+ self.save = None
self.pixbuf = None
self.zoom = None
self.input_text = "text to edit"
@@ -155,8 +158,7 @@ class ImageProcessor(gtk.DrawingArea):
if self.window:
alloc = self.get_allocation()
- rect = gdk.Rectangle(alloc.x, alloc.y,
- alloc.width, alloc.height)
+ rect = gdk.Rectangle(alloc.x, alloc.y,alloc.width, alloc.height)
self.window.invalidate_rect(rect, True)
self.window.process_updates(True)
@@ -214,28 +216,43 @@ class ImageProcessor(gtk.DrawingArea):
self._optimal_zoom_flag = True
if self.window:
im = self.pixbuftoImage(pixbuf)
+ self.undo=im.copy()
im.convert("RGB")
r, g, b = im.split()
im = Image.merge("RGB", (g,g,g))
+ self.redo=im.copy()
pix=self.imagetopixbuf(im)
self.set_pixbuf( pix )
self.window.process_updates( True )
- def image_copy(self,value):
- pixbuf = self.pixbuf
+ def image_undo(self):
self._image_changed_flag = True
self._optimal_zoom_flag = True
if self.window:
- im = self.pixbuftoImage(pixbuf)
- self.im = im.copy()
+ pix=self.imagetopixbuf(self.undo)
+ self.set_pixbuf( pix )
+ self.window.process_updates( True )
- def image_paste(self,value):
- pixbuf = self.pixbuf
+
+ def image_redo(self):
self._image_changed_flag = True
self._optimal_zoom_flag = True
if self.window:
- im = self.im
- pix=self.imagetopixbuf(im)
+ pix=self.imagetopixbuf(self.redo)
+ self.set_pixbuf( pix )
+ self.window.process_updates( True )
+ def image_save(self):
+ pixbuf=self.pixbuf
+ self._image_changed_flag = True
+ self._optimal_zoom_flag = True
+ if self.window:
+ pix=self.pixbuftoImage(pixbuf)
+ self.save=pix.copy()
+ def image_paste(self):
+ self._image_changed_flag = True
+ self._optimal_zoom_flag = True
+ if self.window:
+ pix=self.imagetopixbuf(self.save)
self.set_pixbuf( pix )
self.window.process_updates( True )
@@ -246,7 +263,9 @@ class ImageProcessor(gtk.DrawingArea):
self._optimal_zoom_flag = True
if self.window:
im = self.pixbuftoImage(pixbuf)
+ self.undo=im.copy()
im = im.filter(ImageFilter.BLUR)
+ self.redo=im.copy()
pix=self.imagetopixbuf(im)
self.set_pixbuf( pix )
self.window.process_updates( True )
@@ -258,7 +277,9 @@ class ImageProcessor(gtk.DrawingArea):
self._optimal_zoom_flag = True
if self.window:
im = self.pixbuftoImage(pixbuf)
+ self.undo=im.copy()
im = im.transpose(Image.FLIP_LEFT_RIGHT)
+ self.redo=im.copy()
pix=self.imagetopixbuf(im)
self.set_pixbuf( pix )
self.window.process_updates( True )
@@ -270,8 +291,10 @@ class ImageProcessor(gtk.DrawingArea):
self._optimal_zoom_flag = True
if self.window:
im = self.pixbuftoImage(pixbuf)
+ self.undo=im.copy()
w,h=im.size
im = im.offset(w/2,h/2)
+ self.redo=im.copy()
pix=self.imagetopixbuf(im)
self.set_pixbuf( pix )
self.window.process_updates( True )
@@ -283,7 +306,9 @@ class ImageProcessor(gtk.DrawingArea):
self._optimal_zoom_flag = True
if self.window:
im = self.pixbuftoImage(pixbuf)
+ self.undo=im.copy()
im = im.filter(ImageFilter.CONTOUR)
+ self.redo=im.copy()
pix=self.imagetopixbuf(im)
self.set_pixbuf( pix )
self.window.process_updates( True )
@@ -295,7 +320,9 @@ class ImageProcessor(gtk.DrawingArea):
self._optimal_zoom_flag = True
if self.window:
im = self.pixbuftoImage(pixbuf)
+ self.undo=im.copy()
im = im.filter(ImageFilter.FIND_EDGES)
+ self.redo=im.copy()
pix=self.imagetopixbuf(im)
self.set_pixbuf( pix )
self.window.process_updates( True )
@@ -307,7 +334,9 @@ class ImageProcessor(gtk.DrawingArea):
self._optimal_zoom_flag = True
if self.window:
im = self.pixbuftoImage(pixbuf)
+ self.undo=im.copy()
im = ImageOps.solarize(im, threshold=128)
+ self.redo=im.copy()
pix=self.imagetopixbuf(im)
self.set_pixbuf( pix )
self.window.process_updates( True )
@@ -336,7 +365,9 @@ class ImageProcessor(gtk.DrawingArea):
self.edit_text = edit_text
if self.window:
im = self.pixbuftoImage(pixbuf)
+ self.undo=im.copy()
out=self.Imprint(im, self.input_text,self.edit_text)
+ self.redo=out.copy()
pix=self.imagetopixbuf(out)
self.set_pixbuf( pix )
self.window.process_updates( True )
@@ -373,7 +404,9 @@ class ImageProcessor(gtk.DrawingArea):
self._optimal_zoom_flag = True
if self.window:
im = self.pixbuftoImage(pixbuf)
+ self.undo=im.copy()
im = im.filter(ImageFilter.SHARPEN)
+ self.redo=im.copy()
pix=self.imagetopixbuf(im)
self.set_pixbuf( pix )
self.window.process_updates( True )
@@ -385,7 +418,9 @@ class ImageProcessor(gtk.DrawingArea):
self._optimal_zoom_flag = True
if self.window:
im = self.pixbuftoImage(pixbuf)
+ self.undo=im.copy()
im = im.filter(ImageFilter.EMBOSS)
+ self.redo=im.copy()
pix=self.imagetopixbuf(im)
self.set_pixbuf( pix )
self.window.process_updates( True )
@@ -397,7 +432,9 @@ class ImageProcessor(gtk.DrawingArea):
self._optimal_zoom_flag = True
if self.window:
im = self.pixbuftoImage(pixbuf)
+ self.undo=im.copy()
im = ImageOps.invert(im)
+ self.redo=im.copy()
pix=self.imagetopixbuf(im)
self.set_pixbuf( pix )
self.window.process_updates( True )
@@ -412,6 +449,7 @@ class ImageProcessor(gtk.DrawingArea):
if self.window:
im1=Image.open(mark)
im = self.pixbuftoImage(pixbuf)
+ self.undo=im.copy()
if pos=="tile":
im = self.watermark(im, im1,"tile",0.5)
elif pos=="scale":
@@ -419,6 +457,7 @@ class ImageProcessor(gtk.DrawingArea):
else :#if pos is top_left
im = self.watermark(im, im1,(0,0),0.5)
#(raw_input('type of watermark(tile/scale,(xsize,ysize))')), 0.5)
+ self.redo=im.copy()
pix=self.imagetopixbuf(im)
self.set_pixbuf( pix )
self.window.process_updates( True )
diff --git a/ImageProcessorActivity.py b/ImageProcessorActivity.py
index 25e7e0e..7d41306 100644
--- a/ImageProcessorActivity.py
+++ b/ImageProcessorActivity.py
@@ -44,7 +44,7 @@ from sugar import network
from sugar.datastore import datastore
import telepathy
import dbus
-import pic
+
import ImageProcess
import ProgressDialog
@@ -180,8 +180,10 @@ class ImageProcessorActivity(activity.Activity):
self._view_toolbar.connect('zoom_original', self.__zoom_original_cb)
self._view_toolbar.connect('rotate_clockwise', self.__rotate_anticlockwise_cb)
self._view_toolbar.connect('rotate_anticlockwise', self.__rotate_clockwise_cb)
- self._view_toolbar.connect('copy', self.view.image_copy)
- self._view_toolbar.connect('paste', self.view.image_paste)
+ self._view_toolbar.connect('undo', self.__undo_cb)
+ self._view_toolbar.connect('redo', self.__redo_cb)
+ self._view_toolbar.connect('save', self.__save_cb)
+ self._view_toolbar.connect('paste',self.__paste_cb)
view_toolbar_button = ToolbarButton(page=self._view_toolbar, icon_name='toolbar-view')
self._view_toolbar.show()
toolbar_box.toolbar.insert(view_toolbar_button, -1)
@@ -232,7 +234,7 @@ class ImageProcessorActivity(activity.Activity):
spacer.show()
original_button = ToolButton('original')
- original_button.set_tooltip(_('Undo original pic'))
+ original_button.set_tooltip(_('original pic'))
original_button.connect('clicked', self.view.original_cb)
toolbar_box.toolbar.insert(original_button, -1)
original_button.show()
@@ -261,6 +263,20 @@ class ImageProcessorActivity(activity.Activity):
self.do_load_an_image_cb(button)
self.view.image_Watermark(self.im,pos)
+ def __undo_cb(self, button):
+ self._view_toolbar.undo_button.set_sensitive(self.view.image_undo())
+ self._view_toolbar.redo_button.set_sensitive(True)
+
+ def __redo_cb(self, button):
+ self._view_toolbar.redo_button.set_sensitive(self.view.image_redo())
+ self._view_toolbar.undo_button.set_sensitive(True)
+
+ def __save_cb(self, button):
+ self.view.image_save()
+
+ def __paste_cb(self, button):
+ self.view.image_paste()
+
def __zoom_in_cb(self, button):
self._view_toolbar._zoom_in_button.set_sensitive(self.view.zoom_in())
self._view_toolbar._zoom_out_button.set_sensitive(True)
diff --git a/Imaging/BUILDME b/Imaging/BUILDME
new file mode 100644
index 0000000..91201b1
--- /dev/null
+++ b/Imaging/BUILDME
@@ -0,0 +1,6 @@
+# $Id: BUILDME 1998 2004-09-10 01:31:07Z fredrik $
+# quick build (for lazy programmers). for more information on the
+# build process, see the README file.
+
+python setup.py build_ext -i
+python selftest.py
diff --git a/Imaging/CHANGES b/Imaging/CHANGES
new file mode 100644
index 0000000..4dd67b0
--- /dev/null
+++ b/Imaging/CHANGES
@@ -0,0 +1,1547 @@
+The Python Imaging Library
+$Id: CHANGES 2934 2006-12-03 12:14:00Z fredrik $
+
+ACKNOWLEDGEMENTS: PIL wouldn't be what it is without the help of,
+among others: David Ascher, Phil Austin, Douglas Bagnall, Larry Bates,
+Anthony Baxter, William Baxter, Denis Benoit, Jan Blom, Duncan Booth,
+Jeff Breidenbach, Roger Burnham, Gene Cash, Kevin Cazabon, Fred Clare,
+Greg Coats, Chris Cogdon, Greg Couch, Bill Crutchfield, Abel Deuring,
+Tim Docker, Fred Drake, Graham Dumpleton, Matthew Ellis, Eric
+Etheridge, Robin Friedrich, Pier Paolo Glave, Federico Di Gregorio,
+Markus Gritsch, Daniel Haertle, Greg Hamilton, Mark Hammond, Bernhard
+Herzog, Rob Hooft, Bob Ippolito, Jack Jansen, Bill Janssen, Edward
+Jones, Richard Jones, Håkan Karlsson, Robert Kern, David Kirtley, Bob
+Klimek, Matthias Klose, Andrew Kuchling, Magnus Källström, Victor
+Lacina, Ben Last, Hamish Lawson, Cesare Leonardi, Andrew MacIntyre,
+Jan Matejek, Naveen Michaud-Agrawal, Gordon McMillan, Skip Montanaro,
+Fredrik Nehr, Russell Nelson, Luciano Nocera, Travis Oliphant, Piet
+van Oostrum, Richard Oudkerk, Paul Pharr, Andres Polit, Eric Raymond,
+Victor Reijs, Bertil Reinhammar, Nicholas Riley, Don Rozenberg, Toby
+Sargeant, Barry Scott, Les Schaffer, Joel Shprentz, Klamer Shutte,
+Gene Skonicki, Niki Spahiev, D. Alan Stewart, Perry Stoll, Paul
+Svensson, Ulrik Svensson, Miki Tebeka, Ivan Tkatchev, Dan Torop, Adam
+Twardoch, Rune Uhlin, Dmitry Vasiliev, Sasha Voynow, Charles Waldman,
+Dan Wolfe, and Ka-Ping Yee.
+
+*** Changes from release 1.1.5 to 1.1.6 ***
+
+(1.1.6 released)
+
++ Fixed some 64-bit compatibility warnings for Python 2.5.
+
++ Added threading support for the Sane driver (from Abel Deuring).
+
+(1.1.6b2 released)
+
++ Added experimental "floodfill" function to the ImageDraw module
+ (based on code by Eric Raymond).
+
++ The default arguments for "frombuffer" doesn't match "fromstring"
+ and the documentation; this is a bug, and will most likely be fixed
+ in a future version. In this release, PIL prints a warning message
+ instead. To silence the warning, change any calls of the form
+ "frombuffer(mode, size, data)" to
+
+ frombuffer(mode, size, data, "raw", mode, 0, 1)
+
++ Added "fromarray" function, which takes an object implementing the
+ NumPy array interface and creates a PIL Image from it. (from Travis
+ Oliphant).
+
++ Added NumPy array interface support (__array_interface__) to the
+ Image class (based on code by Travis Oliphant).
+
+ This allows you to easily convert between PIL image memories and
+ NumPy arrays:
+
+ import numpy, Image
+
+ im = Image.open('lena.jpg')
+
+ a = numpy.asarray(im) # a is readonly
+
+ im = Image.fromarray(a)
+
++ Fixed CMYK polarity for JPEG images, by treating all images as
+ "Adobe CMYK" images. (thanks to Cesare Leonardi and Kevin Cazabon
+ for samples, debugging, and patches).
+
+(1.1.6b1 released)
+
++ Added 'expand' option to the Image 'rotate' method. If true, the
+ output image is made large enough to hold the entire rotated image.
+
++ Changed the ImageDraw 'line' method to always draw the last pixel in
+ a polyline, independent of line angle.
+
++ Fixed bearing calculation and clipping in the ImageFont truetype
+ renderer; this could lead to clipped text, or crashes in the low-
+ level _imagingft module. (based on input from Adam Twardoch and
+ others).
+
++ Added ImageQt wrapper module, for converting PIL Image objects to
+ QImage objects in an efficient way.
+
++ Fixed 'getmodebands' to return the number of bands also for "PA"
+ and "LA" modes. Added 'getmodebandnames' helper that return the
+ band names.
+
+(1.1.6a2 released)
+
++ Added float/double support to the TIFF loader (from Russell
+ Nelson).
+
++ Fixed broken use of realloc() in path.c (from Jan Matejek)
+
++ Added save support for Spider images (from William Baxter).
+
++ Fixed broken 'paste' and 'resize' operations in pildriver
+ (from Bill Janssen).
+
++ Added support for duplex scanning to the Sane interface (Abel
+ Deuring).
+
+(1.1.6a1 released)
+
++ Fixed a memory leak in "convert(mode)", when converting from
+ L to P.
+
++ Added pixel access object. The "load" method now returns a
+ access object that can be used to directly get and set pixel
+ values, using ordinary [x, y] notation:
+
+ pixel = im.load()
+ v = pixel[x, y]
+ pixel[x, y] = v
+
+ If you're accessing more than a few pixels, this is a lot
+ faster than using getpixel/putpixel.
+
++ Fixed building on Cygwin (from Miki Tebeka).
+
++ Fixed "point(callable)" on unloaded images (reported by Håkan
+ Karlsson).
+
++ Fixed size bug in ImageWin.ImageWindow constructor (from Victor
+ Reijs)
+
++ Fixed ImageMath float() and int() operations for Python 2.4
+ (reported by Don Rozenberg).
+
++ Fixed "RuntimeError: encoder error -8 in tostring" problem for
+ wide "RGB", "I", and "F" images.
+
++ Fixed line width calculation.
+
+(1.1.6a0 released)
+
++ Fixed byte order issue in Image.paste(ink) (from Ka-Ping Yee).
+
++ Fixed off-by-0.5 errors in the ANTIALIAS code (based on input
+ from Douglas Bagnall).
+
++ Added buffer interface support to the Path constructor. If
+ a buffer is provided, it is assumed to contain a flat array
+ of float coordinates (e.g. array.array('f', seq)).
+
++ Added new ImageMath module.
+
++ Fixed ImageOps.equalize when used with a small number of distinct
+ values (reported by David Kirtley).
+
++ Fixed potential integer division in PSDraw.image (from Eric Etheridge).
+
+*** Changes from release 1.1 to 1.1.5 ***
+
+(1.1.5c2 and 1.1.5 final released)
+
++ Added experimental PERSPECTIVE transform method (from Jeff Breiden-
+ bach).
+
+(1.1.5c1 released)
+
++ Make sure "thumbnail" never generates zero-wide or zero-high images
+ (reported by Gene Skonicki)
+
++ Fixed a "getcolors" bug that could result in a zero count for some
+ colors (reported by Richard Oudkerk).
+
++ Changed default "convert" palette to avoid "rounding errors" when
+ round-tripping white source pixels (reported by Henryk Gerlach and
+ Jeff Epler).
+
+(1.1.5b3 released)
+
++ Don't crash in "quantize" method if the number of colors requested
+ is larger than 256. This release raises a ValueError exception;
+ future versions may return a mode "RGB" image instead (reported
+ by Richard Oudkerk).
+
++ Added WBMP read/write support (based on code by Duncan Booth).
+
+(1.1.5b2 released)
+
++ Added DPI read/write support to the PNG codec. The decoder sets
+ the info["dpi"] attribute for PNG files with appropriate resolution
+ settings. The encoder uses the "dpi" option (based on code by Niki
+ Spahiev).
+
++ Added limited support for "point" mappings from mode "I" to mode "L".
+ Only 16-bit values are supported (other values are clipped), the lookup
+ table must contain exactly 65536 entries, and the mode argument must be
+ set to "L".
+
++ Added support for Mac OS X icns files (based on code by Bob Ippolito).
+
++ Added "ModeFilter" support to the ImageFilter module.
+
++ Added support for Spider images (from William Baxter). See the
+ comments in PIL/SpiderImagePlugin.py for more information on this
+ format.
+
+(1.1.5b1 released)
+
++ Added new Sane release (from Ralph Heinkel). See the Sane/README
+ and Sane/CHANGES files for more information.
+
++ Added experimental PngInfo chunk container to the PngImageFile
+ module. This can be used to add arbitrary chunks to a PNG file.
+ Create a PngInfo instance, use "add" or "add_text" to add chunks,
+ and pass the instance as the "pnginfo" option when saving the
+ file.
+
++ Added "getpalette" method. This returns the palette as a list,
+ or None if the image has no palette. To modify the palette, use
+ "getpalette" to fetch the current palette, modify the list, and
+ put it back using "putpalette".
+
++ Added optional flattening to the ImagePath "tolist" method.
+ tolist() or tolist(0) returns a list of 2-tuples, as before.
+ tolist(1) returns a flattened list instead.
+
+(1.1.5a5 released)
+
++ Fixed BILINEAR/BICUBIC/ANTIALIAS filtering for mode "LA".
+
++ Added "getcolors()" method. This is similar to the existing histo-
+ gram method, but looks at color values instead of individual layers,
+ and returns an unsorted list of (count, color) tuples.
+
+ By default, the method returns None if finds more than 256 colors.
+ If you need to look for more colors, you can pass in a limit (this
+ is used to allocate internal tables, so you probably don't want to
+ pass in too large values).
+
++ Build improvements: Fixed building under AIX, improved detection of
+ FreeType2 and Mac OS X framework libraries, and more. Many thanks
+ to everyone who helped test the new "setup.py" script!
+
+(1.1.5a4 released)
+
++ The "save" method now looks for a file format driver before
+ creating the file.
+
++ Don't use antialiased truetype fonts when drawing in mode "P", "I",
+ and "F" images.
+
++ Rewrote the "setup.py" file. The new version scans for available
+ support libraries, and configures both the libImaging core library
+ and the bindings in one step.
+
+ To use specific versions of the libraries, edit the ROOT variables
+ in the setup.py file.
+
++ Removed threaded "show" viewer; use the old "show" implementation
+ instead (Windows).
+
++ Added deprecation warnings to Image.offset, ImageDraw.setink, and
+ ImageDraw.setfill.
+
++ Added width option to ImageDraw.line(). The current implementation
+ works best for straight lines; it does not support line joins, so
+ polylines won't look good.
+
++ ImageDraw.Draw is now a factory function instead of a class. If
+ you need to create custom draw classes, inherit from the ImageDraw
+ class. All other code should use the factory function.
+
++ Fixed loading of certain PCX files (problem reported by Greg
+ Hamilton, who also provided samples).
+
++ Changed _imagingft.c to require FreeType 2.1 or newer. The
+ module can still be built with earlier versions; see comments
+ in _imagingft.c for details.
+
+(1.1.5a3 released)
+
++ Added 'getim' method, which returns a PyCObject wrapping an
+ Imaging pointer. The description string is set to IMAGING_MAGIC.
+ See Imaging.h for pointer and string declarations.
+
++ Fixed reading of TIFF JPEG images (problem reported by Ulrik
+ Svensson).
+
++ Made ImageColor work under Python 1.5.2
+
++ Fixed division by zero "equalize" on very small images (from
+ Douglas Bagnall).
+
+(1.1.5a2 released)
+
++ The "paste" method now supports the alternative "paste(im, mask)"
+ syntax (in this case, the box defaults to im's bounding box).
+
++ The "ImageFile.Parser" class now works also for PNG files with
+ more than one IDAT block.
+
++ Added DPI read/write to the TIFF codec, and fixed writing of
+ rational values. The decoder sets the info["dpi"] attribute
+ for TIFF files with appropriate resolution settings. The
+ encoder uses the "dpi" option.
+
++ Disable interlacing for small (or narrow) GIF images, to
+ work around what appears to be a hard-to-find bug in PIL's
+ GIF encoder.
+
++ Fixed writing of mode "P" PDF images. Made mode "1" PDF
+ images smaller.
+
++ Made the XBM reader a bit more robust; the file may now start
+ with a few whitespace characters.
+
++ Added support for enhanced metafiles to the WMF driver. The
+ separate PILWMF kit lets you render both placeable WMF files
+ and EMF files as raster images. See
+
+ http://effbot.org/downloads#pilwmf
+
+(1.1.5a1 released)
+
++ Replaced broken WMF driver with a WMF stub plugin (see below).
+
++ Fixed writing of mode "1", "L", and "CMYK" PDF images (based on
+ input from Nicholas Riley and others).
+
++ Fixed adaptive palette conversion for zero-width or zero-height
+ images (from Chris Cogdon)
+
++ Fixed reading of PNG images from QuickTime 6 (from Paul Pharr)
+
++ Added support for StubImageFile plugins, including stub plugins
+ for BUFR, FITS, GRIB, and HDF5 files. A stub plugin can identify
+ a given file format, but relies on application code to open and
+ save files in that format.
+
++ Added optional "encoding" argument to the ImageFont.truetype
+ factory. This argument can be used to specify non-Unicode character
+ maps for fonts that support that. For example, to draw text using
+ the Microsoft Symbol font, use:
+
+ font = ImageFont.truetype("symbol.ttf", 16, encoding="symb")
+ draw.text((0, 0), unichr(0xF000 + 0xAA))
+
+ (note that the symbol font uses characters in the 0xF000-0xF0FF
+ range)
+
+ Common encodings are "unic" (Unicode), "symb" (Microsoft Symbol),
+ "ADOB" (Adobe Standard), "ADBE" (Adobe Expert), and "armn" (Apple
+ Roman). See the FreeType documentation for more information.
+
++ Made "putalpha" a bit more robust; you can now attach an alpha
+ layer to a plain "L" or "RGB" image, and you can also specify
+ constant alphas instead of alpha layers (using integers or colour
+ names).
+
++ Added experimental "LA" mode support.
+
+ An "LA" image is an "L" image with an attached transparency layer.
+ Note that support for "LA" is not complete; some operations may
+ fail or produce unexpected results.
+
++ Added "RankFilter", "MinFilter", "MedianFilter", and "MaxFilter"
+ classes to the ImageFilter module.
+
++ Improved support for applications using multiple threads; PIL
+ now releases the global interpreter lock for many CPU-intensive
+ operations (based on work by Kevin Cazabon).
+
++ Ignore Unicode characters in the PCF loader (from Andres Polit)
+
++ Fixed typo in OleFileIO.loadfat, which could affect loading of
+ FlashPix and Image Composer images (Daniel Haertle)
+
++ Fixed building on platforms that have Freetype but don't have
+ Tcl/Tk (Jack Jansen, Luciano Nocera, Piet van Oostrum and others)
+
++ Added EXIF GPSInfo read support for JPEG files. To extract
+ GPSInfo information, open the file, extract the exif dictionary,
+ and check for the key 0x8825 (GPSInfo). If present, it contains
+ a dictionary mapping GPS keys to GPS values. For a list of keys,
+ see the EXIF specification.
+
+ The "ExifTags" module contains a GPSTAGS dictionary mapping GPS
+ tags to tag names.
+
++ Added DPI read support to the PCX and DCX codecs (info["dpi"]).
+
++ The "show" methods now uses a built-in image viewer on Windows.
+ This viewer creates an instance of the ImageWindow class (see
+ below) and keeps it running in a separate thread. NOTE: This
+ was disabled in 1.1.5a4.
+
++ Added experimental "Window" and "ImageWindow" classes to the
+ ImageWin module. These classes allow you to create a WCK-style
+ toplevel window, and use it to display raster data.
+
++ Fixed some Python 1.5.2 issues (to build under 1.5.2, use the
+ Makefile.pre.in/Setup.in approach)
+
++ Added support for the TIFF FillOrder tag. PIL can read mode "1",
+ "L", "P" and "RGB" images with non-standard FillOrder (based on
+ input from Jeff Breidenbach).
+
+(1.1.4 final released)
+
++ Fixed ImageTk build problem on Unix.
+
+(1.1.4b2 released)
+
++ Improved building on Mac OS X (from Jack Jansen).
+
++ Improved building on Windows with MinGW (from Klamer Shutte).
+
++ If no font is specified, ImageDraw now uses the embedded default
+ font. Use the "load" or "truetype" methods to load a real font.
+
++ Added embedded default font to the ImageFont module (currently
+ an 8-pixel Courier font, taken from the X window distribution).
+
+(1.1.4b1 released)
+
++ Added experimental EXIF support for JPEG files. To extract EXIF
+ information from a JPEG file, open the file as usual, and call the
+ "_getexif" method. If successful, this method returns a dictionary
+ mapping EXIF TIFF tags to values. If the file does not contain EXIF
+ data, the "_getexif" method returns None.
+
+ The "ExifTags" module contains a dictionary mapping tags to tag
+ names.
+
+ This interface will most likely change in future versions.
+
++ Fixed a bug when using the "transparency" option with the GIF
+ writer.
+
++ Added limited support for "bitfield compression" in BMP files
+ and DIB buffers, for 15-bit, 16-bit, and 32-bit images. This
+ also fixes a problem with ImageGrab module when copying screen-
+ dumps from the clipboard on 15/16/32-bit displays.
+
++ Added experimental WAL (Quake 2 textures) loader. To use this
+ loader, import WalImageFile and call the "open" method in that
+ module.
+
+(1.1.4a4 released)
+
++ Added updated SANE driver (Andrew Kuchling, Abel Deuring)
+
++ Use Python's "mmap" module on non-Windows platforms to read some
+ uncompressed formats using memory mapping. Also added a "frombuffer"
+ function that allows you to access the contents of an existing string
+ or buffer object as if it were an image object.
+
++ Fixed a memory leak that could appear when processing mode "P"
+ images (from Pier Paolo Glave)
+
++ Ignore Unicode characters in the BDF loader (from Graham Dumpleton)
+
+(1.1.4a3 released; windows only)
+
++ Added experimental RGBA-on-RGB drawing support. To use RGBA
+ colours on an RGB image, pass "RGBA" as the second string to
+ the ImageDraw.Draw constructor.
+
++ Added support for non-ASCII strings (Latin-1) and Unicode
+ to the truetype font renderer.
+
++ The ImageWin "Dib" object can now be constructed directly from
+ an image object.
+
++ The ImageWin module now allows you use window handles as well
+ as device contexts. To use a window handle, wrap the handle in
+ an ImageWin.HWND object, and pass in this object instead of the
+ device context.
+
+(1.1.4a2 released)
+
++ Improved support for 16-bit unsigned integer images (mode "I;16").
+ This includes TIFF reader support, and support for "getextrema"
+ and "point" (from Klamer Shutte).
+
++ Made the BdfFontFile reader a bit more robust (from Kevin Cazabon
+ and Dmitry Vasiliev)
+
++ Changed TIFF writer to always write Compression tag, even when
+ using the default compression (from Greg Couch).
+
++ Added "show" support for Mac OS X (from Dan Wolfe).
+
++ Added clipboard support to the "ImageGrab" module (Windows only).
+ The "grabclipboard" function returns an Image object, a list of
+ filenames (not in 1.1.4), or None if neither was found.
+
+(1.1.4a1 released)
+
++ Improved support for drawing RGB data in palette images. You can
+ now use RGB tuples or colour names (see below) when drawing in a
+ mode "P" image. The drawing layer automatically assigns color
+ indexes, as long as you don't use more than 256 unique colours.
+
++ Moved self test from MiniTest/test.py to ./selftest.py.
+
++ Added support for CSS3-style color strings to most places that
+ accept colour codes/tuples. This includes the "ImageDraw" module,
+ the Image "new" function, and the Image "paste" method.
+
+ Colour strings can use one of the following formats: "#f00",
+ "#ff0000", "rgb(255,0,0)", "rgb(100%,0%,0%)", "hsl(0, 100%, 50%)",
+ or "red" (most X11-style colour names are supported). See the
+ documentation for the "ImageColor" module for more information.
+
++ Fixed DCX decoder (based on input from Larry Bates)
+
++ Added "IptcImagePlugin.getiptcinfo" helper to extract IPTC/NAA
+ newsphoto properties from JPEG, TIFF, or IPTC files.
+
++ Support for TrueType/OpenType fonts has been added to
+ the standard distribution. You need the freetype 2.0
+ library.
+
++ Made the PCX reader a bit more robust when reading 2-bit
+ and 4-bit PCX images with odd image sizes.
+
++ Added "Kernel" class to the ImageFilter module. This class
+ allows you to filter images with user-defined 3x3 and 5x5
+ convolution kernels.
+
++ Added "putdata" support for mode "I", "F" and "RGB".
+
++ The GIF writer now supports the transparency option (from
+ Denis Benoit).
+
++ A HTML version of the module documentation is now shipped
+ with the source code distribution. You'll find the files in
+ the Doc subdirectory.
+
++ Added support for Palm pixmaps (from Bill Janssen). This
+ change was listed for 1.1.3, but the "PalmImagePlugin" driver
+ didn't make it into the distribution.
+
++ Improved decoder error messages.
+
+(1.1.3 final released)
+
++ Made setup.py look for old versions of zlib. For some back-
+ ground, see: http://www.gzip.org/zlib/advisory-2002-03-11.txt
+
+(1.1.3c2 released)
+
++ Added setup.py file (tested on Unix and Windows). You still
+ need to build libImaging/imaging.lib in the traditional way,
+ but the setup.py script takes care of the rest.
+
+ The old Setup.in/Makefile.pre.in build method is still
+ supported.
+
++ Fixed segmentation violation in ANTIALIAS filter (an internal
+ buffer wasn't properly allocated).
+
+(1.1.3c1 released)
+
++ Added ANTIALIAS downsampling filter for high-quality "resize"
+ and "thumbnail" operations. Also added filter option to the
+ "thumbnail" operation; the default value is NEAREST, but this
+ will most likely change in future versions.
+
++ Fixed plugin loader to be more robust if the __file__
+ variable isn't set.
+
++ Added seek/tell support (for layers) to the PhotoShop
+ loader. Layer 0 is the main image.
+
++ Added new (but experimental) "ImageOps" module, which provides
+ shortcuts for commonly used operations on entire images.
+
++ Don't mess up when loading PNG images if the decoder leaves
+ data in the output buffer. This could cause internal errors
+ on some PNG images, with some versions of ZLIB. (Bug report
+ and patch provided by Bernhard Herzog.)
+
++ Don't mess up on Unicode filenames.
+
++ Don't mess up when drawing on big endian platforms.
+
++ Made the TIFF loader a bit more robust; it can now read some
+ more slightly broken TIFF files (based on input from Ted Wright,
+ Bob Klimek, and D. Alan Stewart)
+
++ Added OS/2 EMX build files (from Andrew MacIntyre)
+
++ Change "ImageFont" to reject image files if they don't have the
+ right mode. Older versions could leak memory for "P" images.
+ (Bug reported by Markus Gritsch).
+
++ Renamed some internal functions to avoid potential build
+ problem on Mac OS X.
+
++ Added DL_EXPORT where relevant (for Cygwin, based on input
+ from Robert Yodlowski)
+
++ (re)moved bogus __init__ call in BdfFontFile (bug spotted
+ by Fred Clare)
+
++ Added "ImageGrab" support (Windows only)
+
++ Added support for XBM hotspots (based on code contributed by
+ Bernhard Herzog).
+
++ Added write support for more TIFF tags, namely the Artist,
+ Copyright, DateTime, ResolutionUnit, Software, XResolution and
+ YResolution tags (from Greg Couch)
+
++ Added TransposedFont wrapper to ImageFont module
+
++ Added "optimize" flag to GIF encoder. If optimize is present
+ and non-zero, PIL will work harder to create a small file.
+
++ Raise "EOFError" (not IndexError) when reading beyond the
+ end of a TIFF sequence.
+
++ Support rewind ("seek(0)") for GIF and TIFF sequences.
+
++ Load grayscale GIF images as mode "L"
+
++ Added DPI read/write support to the JPEG codec. The decoder
+ sets the info["dpi"] attribute for JPEG files with JFIF dpi
+ settings. The encoder uses the "dpi" option:
+
+ im = Image.open("file.jpg")
+ dpi = im.info["dpi"] # raises KeyError if DPI not known
+ im.save("out.jpg", dpi=dpi)
+
+ Note that PIL doesn't always preserve the "info" attribute
+ for normal image operations.
+
+(1.1.2c1 and 1.1.2 final released)
+
++ Adapted to Python 2.1. Among other things, all uses of the
+ "regex" module has been repleased with "re".
+
++ Fixed attribute error when reading large PNG files (this bug
+ was introduced in maintenance code released after the 1.1.1
+ release)
+
++ Ignore non-string objects in sys.path
+
++ Fixed Image.transform(EXTENT) for negative xoffsets
+
++ Fixed loading of image plugins if PIL is installed as a package.
+ (The plugin loader now always looks in the directory where the
+ Image.py module itself is found, even if that directory isn't on
+ the standard search path)
+
++ The Png plugin has been added to the list of preloaded standard
+ formats
+
++ Fixed bitmap/text drawing in fill mode.
+
++ Fixed "getextrema" to work also for multiband images.
+
++ Added transparency support for L and P images to the PNG codec.
+
++ Improved support for read-only images. The "load" method now
+ sets the "readonly" attribute for memory-mapped images. Operations
+ that modifies an image in place (such as "paste" and drawing operations)
+ creates an in-memory copy of the image, if necessary. (before this
+ change, any attempt to modify a memory-mapped image resulted in a
+ core dump...)
+
++ Added special cases for lists everywhere PIL expects a sequence.
+ This should speed up things like "putdata" and drawing operations.
+
++ The Image.offset method is deprecated. Use the ImageChops.offset
+ function instead.
+
++ Changed ImageChops operators to copy palette and info dictionary
+ from the first image argument.
+
+(1.1.1 released)
+
++ Additional fixes for Python 1.6/2.0, including TIFF "save" bug.
+
++ Changed "init" to properly load plugins when PIL is used as a
+ package.
+
++ Fixed broken "show" method (on Unix)
+
+*** Changes from release 1.0 to 1.1 ***
+
++ Adapted to Python 1.6 ("append" and other method changes)
+
++ Fixed Image.paste when pasting with solid colour and matte
+ layers ("L" or "RGBA" masks) (bug reported by Robert Kern)
+
++ To make it easier to distribute prebuilt versions of PIL,
+ the tkinit binding stuff has been moved to a separate
+ extension module, named "_imagingtk".
+
+*** Changes from release 0.3b2 to 1.0 final ***
+
++ If there's no 16-bit integer (like on a Cray T3E), set
+ INT16 to the smallest integer available. Most of the
+ library works just fine anyway (from Bill Crutchfield)
+
++ Tweaks to make drawing work on big-endian platforms.
+
+(1.0c2 released)
+
++ If PIL is built with the WITH_TKINTER flag, ImageTk can
+ automatically hook into a standard Tkinter build. You
+ no longer need to build your own Tkinter to use the
+ ImageTk module.
+
+ The old way still works, though. For more information,
+ see Tk/install.txt.
+
++ Some tweaks to ImageTk to support multiple Tk interpreters
+ (from Greg Couch).
+
++ ImageFont "load_path" now scans directory mentioned in .pth
+ files (from Richard Jones).
+
+(1.0c1 released)
+
++ The TIFF plugin has been rewritten. The new plugin fully
+ supports all major PIL image modes (including F and I).
+
++ The ImageFile module now includes a Parser class, which can
+ be used to incrementally decode an image file (while down-
+ loading it from the net, for example). See the handbook for
+ details.
+
++ "show" now converts non-standard modes to "L" or "RGB" (as
+ appropriate), rather than writing weird things to disk for
+ "xv" to choke upon. (bug reported by Les Schaffer).
+
+(1.0b2 released)
+
++ Major speedups for rotate, transform(EXTENT), and transform(AFFINE)
+ when using nearest neighbour resampling.
+
++ Modified ImageDraw to be compatible with the Arrow graphics
+ interface. See the handbook for details.
+
++ PIL now automatically loads file codecs when used as a package
+ (from The Dragon De Monsyne). Also included an __init__.py file
+ in the standard distribution.
+
++ The GIF encoder has been modified to produce much smaller files.
+
+ PIL now uses a run-length encoding method to encode GIF files.
+ On a random selection of GIF images grabbed from the web, this
+ version makes the images about twice as large as the original
+ LZW files, where the earlier version made them over 5 times
+ larger. YMMV, of course.
+
++ Added PCX write support (works with "1", "P", "L", and "RGB")
+
++ Added "bitmap" and "textsize" methods to ImageDraw.
+
++ Improved font rendering code. Fixed a bug or two, and moved
+ most of the time critical stuff to C.
+
++ Removed "bdf2pil.py". Use "pilfont.py" instead!
+
++ Improved 16-bit support (still experimental, though).
+
+ The following methods now support "I;16" and "I;16B" images:
+ "getpixel", "copy", "convert" (to and from mode "I"), "resize",
+ "rotate", and "transform" with nearest neighbour filters, and
+ "save" using the IM format. The "new" and "open" functions
+ also work as expected. On Windows, 16-bit files are memory
+ mapped.
+
+ NOTE: ALL other operations are still UNDEFINED on 16-bit images.
+
++ The "paste" method now supports constant sources.
+
+ Just pass a colour value (a number or a tuple, depending on
+ the target image mode) instead of the source image.
+
+ This was in fact implemented in an inefficient way in
+ earlier versions (the "paste" method generated a temporary
+ source image if you passed it a colour instead of an image).
+ In this version, this is handled on the C level instead.
+
++ Added experimental "RGBa" mode support.
+
+ An "RGBa" image is an RGBA image where the colour components
+ have have been premultipled with the alpha value. PIL allows
+ you to convert an RGBA image to an RGBa image, and to paste
+ RGBa images on top of RGB images. Since this saves a bunch
+ of multiplications and shifts, it is typically about twice
+ as fast an ordinary RGBA paste.
+
++ Eliminated extra conversion step when pasting "RGBA" or "RGBa"
+ images on top of "RGB" images.
+
++ Fixed Image.BICUBIC resampling for "RGB" images.
+
++ Fixed PCX image file handler to properly read 8-bit PCX
+ files (bug introduced in 1.0b1, reported by Bernhard
+ Herzog)
+
++ Fixed PSDraw "image" method to restore the coordinate
+ system.
+
++ Fixed "blend" problem when applied to images that was
+ not already loaded (reported by Edward C. Jones)
+
++ Fixed -f option to "pilconvert.py" (from Anthony Baxter)
+
+(1.0b1 released)
+
++ Added Toby J. Sargeant's quantization package. To enable
+ quantization, use the "palette" option to "convert":
+
+ imOut = im.convert("P", palette=Image.ADAPTIVE)
+
+ This can be used with "L", "P", and "RGB" images. In this
+ version, dithering cannot be used with adaptive palettes.
+
+ Note: ADAPTIVE currently maps to median cut quantization
+ with 256 colours. The quantization package also contains
+ a maximum coverage quantizer, which will be supported by
+ future versions of PIL.
+
++ Added Eric S. Raymond's "pildriver" image calculator to the
+ distribution. See the docstring for more information.
+
++ The "offset" method no longer dumps core if given positive
+ offsets (from Charles Waldman).
+
++ Fixed a resource leak that could cause ImageWin to run out of
+ GDI resources (from Roger Burnham).
+
++ Added "arc", "chord", and "pieslice" methods to ImageDraw (inspired
+ by code contributed by Richard Jones).
+
++ Added experimental 16-bit support, via modes "I;16" (little endian
+ data) and "I;16B" (big endian). Only a few methods properly support
+ such images (see above).
+
++ Added XV thumbnail file handler (from Gene Cash).
+
++ Fixed BMP image file handler to handle palette images with small
+ palettes (from Rob Hooft).
+
++ Fixed Sun raster file handler for palette images (from Charles
+ Waldman).
+
++ Improved various internal error messages.
+
++ Fixed Path constructor to handle arbitrary sequence objects. This
+ also affects the ImageDraw class (from Richard Jones).
+
++ Fixed a bug in JpegDecode that caused PIL to report "decoder error
+ -2" for some progressive JPEG files (reported by Magnus Källström,
+ who also provided samples).
+
++ Fixed a bug in JpegImagePlugin that caused PIL to hang when loading
+ JPEG files using 16-bit quantization tables.
+
++ The Image "transform" method now supports Image.QUAD transforms.
+ The data argument is an 8-tuple giving the upper left, lower
+ left, lower right, and upper right corner of the source quadri-
+ lateral. Also added Image.MESH transform which takes a list
+ of quadrilaterals.
+
++ The Image "resize", "rotate", and "transform" methods now support
+ Image.BILINEAR (2x2) and Image.BICUBIC (4x4) resampling filters.
+ Filters can be used with all transform methods.
+
++ The ImageDraw "rectangle" method now includes both the right
+ and the bottom edges when drawing filled rectangles.
+
++ The TGA decoder now works properly for runlength encoded images
+ which have more than one byte per pixel.
+
++ "getbands" on an YCbCr image now returns ("Y", "Cb", "Cr")
+
++ Some file drivers didn't handle the optional "modify" argument
+ to the load method. This resulted in exceptions when you used
+ "paste" (and other methods that modify an image in place) on a
+ newly opened file.
+
+*** Changes from release 0.2 (b5) to 0.3 (b2) ***
+
+(0.3b2 released)
+
+The test suite includes 825 individual tests.
+
++ An Image "getbands" method has been added. It returns a tuple
+ containing the individual band names for this image. To figure
+ out how many bands an image has, use "len(im.getbands())".
+
++ An Image "putpixel" method has been added.
+
++ The Image "point" method can now be used to convert "L" images
+ to any other format, via a lookup table. That table should
+ contain 256 values for each band in the output image.
+
++ Some file drivers (including FLI/FLC, GIF, and IM) accidently
+ overwrote the offset method with an internal attribute. All
+ drivers have been updated to use private attributes where
+ possible.
+
++ The Image "histogram" method now works for "I" and "F" images.
+ For these modes, PIL divides the range between the min and
+ max values used in the image into 256 bins. You can also
+ pass in your own min and max values via the "extrema" option:
+
+ h = im.histogram(extrema=(0, 255))
+
++ An Image "getextrema" method has been added. It returns the
+ min and max values used in the image. In this release, this
+ works for single band images only.
+
++ Changed the PNG driver to load and save mode "I" images as
+ 16-bit images. When saving, values outside the range 0..65535
+ are clipped.
+
++ Fixed ImageFont.py to work with the new "pilfont" compiler.
+
++ Added JPEG "save" and "draft" support for mode "YCbCr" images.
+ Note that if you save an "YCbCr" image as a JPEG file and read
+ it back, it is read as an RGB file. To get around this, you
+ can use the "draft" method:
+
+ im = Image.open("color.jpg")
+ im.draft("YCbCr", im.size)
+
++ Read "RGBA" TGA images. Also fixed the orientation bug; all
+ images should now come out the right way.
+
++ Changed mode name (and internal representation) from "YCrCb"
+ to "YCbCr" (!)
+ *** WARNING: MAY BREAK EXISTING CODE ***
+
+(0.3b1 released)
+
+The test suite includes 750 individual tests.
+
++ The "pilfont" package is now included in the standard PIL
+ distribution. The pilfont utility can be used to convert
+ X BDF and PCF raster font files to a format understood by
+ the ImageFont module.
+
++ GIF files are now interlaced by default. To write a
+ non-interlaced file, pass interlace=0 to the "save"
+ method.
+
++ The default string format has changed for the "fromstring"
+ and "tostring" methods.
+ *** WARNING: MAY BREAK EXISTING CODE ***
+
+ NOTE: If no extra arguments are given, the first line in
+ the string buffer is the top line of the image, instead of
+ the bottom line. For RGB images, the string now contains
+ 3 bytes per pixel instead of 4. These changes were made
+ to make the methods compatible with the "fromstring"
+ factory function.
+
+ To get the old behaviour, use the following syntax:
+
+ data = im.tostring("raw", "RGBX", 0, -1)
+ im.fromstring(data, "raw", "RGBX", 0, -1)
+
++ "new" no longer gives a MemoryError if the width or height
+ is zero (this only happened on platforms where malloc(0)
+ or calloc(0) returns NULL).
+
++ "new" now adds a default palette object to "P" images.
+
++ You can now convert directly between all modes supported by
+ PIL. When converting colour images to "P", PIL defaults to
+ a "web" palette and dithering. When converting greyscale
+ images to "1", PIL uses a thresholding and dithering.
+
++ Added a "dither" option to "convert". By default, "convert"
+ uses floyd-steinberg error diffusion for "P" and "1" targets,
+ so this option is only used to *disable* dithering. Allowed
+ values are NONE (no dithering) or FLOYDSTEINBERG (default).
+
+ imOut = im.convert("P", dither=Image.NONE)
+
++ Added a full set of "I" decoders. You can use "fromstring"
+ (and file decoders) to read any standard integer type as an
+ "I" image.
+
++ Added some support for "YCbCr" images (creation, conversion
+ from/to "L" and "RGB", IM YCC load/save)
+
++ "getpixel" now works properly with fractional coordinates.
+
++ ImageDraw "setink" now works with "I", "F", "RGB", "RGBA",
+ "RGBX", "CMYK", and "YCbCr" images.
+
++ ImImagePlugin no longer attaches palettes to "RGB" images.
+
++ Various minor fixes.
+
+(0.3a4 released)
+
++ Added experimental IPTC/NAA support.
+
++ Eliminated AttributeError exceptions after "crop" (from
+ Skip Montanaro)
+
++ Reads some uncompressed formats via memory mapping (this
+ is currently supported on Win32 only)
+
++ Fixed some last minute glitches in the last alpha release
+ (Types instead of types in Image.py, version numbers, etc.)
+
++ Eliminated some more bogus compiler warnings.
+
++ Various fixes to make PIL compile and run smoother on Macs
+ (from Jack Jansen).
+
++ Fixed "fromstring" and "tostring" for mode "I" images.
+
+(0.3a3 released)
+
+The test suite includes 530 individual tests.
+
++ Eliminated unexpected side-effect in "paste" with matte. "paste"
+ now works properly also if compiled with "gcc".
+
++ Adapted to Python 1.5 (build issues only)
+
++ Fixed the ImageDraw "point" method to draw also the last
+ point (!).
+
++ Added "I" and "RGBX" support to Image.new.
+
++ The plugin path is now properly prepended to the module search
+ path when a plugin module is imported.
+
++ Added "draw" method to the ImageWin.Dib class. This is used by
+ Topaz to print images on Windows printers.
+
++ "convert" now supports conversions from "P" to "1" and "F".
+
++ "paste" can now take a colour instead of an image as the first argument.
+ The colour must match the colour argument given to the new function, and
+ match the mode of the target image.
+
++ Fixed "paste" to allow a mask also for mode "F" images.
+
++ The BMP driver now saves mode "1" images. When loading images, the mode
+ is set to "L" for 8-bit files with greyscale palettes, and to "P" for
+ other 8-bit files.
+
++ The IM driver now reads and saves "1" images (file modes "0 1" or "L 1").
+
++ The JPEG and GIF drivers now saves "1" images. For JPEG, the image
+ is saved as 8-bit greyscale (it will load as mode "L"). For GIF, the
+ image will be loaded as a "P" image.
+
++ Fixed a potential buffer overrun in the GIF encoder.
+
+(0.3a2 released)
+
+The test suite includes 400 individual tests.
+
++ Improvements to the test suite revealed a number of minor bugs, which
+ are all fixed. Note that crop/paste, 32-bit ImageDraw, and ImageFont
+ are still weak spots in this release.
+
++ Added "putpalette" method to the Image class. You can use this
+ to add or modify the palette for "P" and "L" images. If a palette
+ is added to an "L" image, it is automatically converted to a "P"
+ image.
+
++ Fixed ImageDraw to properly handle 32-bit image memories
+ ("RGB", "RGBA", "CMYK", "F")
+
++ Fixed "fromstring" and "tostring" not to mess up the mode attribute
+ in default mode.
+
++ Changed ImPlatform.h to work on CRAY's (don't have one at home, so I
+ haven't tried it). The previous version assumed that either "short"
+ or "int" were 16-bit wide. PIL still won't compile on platforms where
+ neither "short", "int" nor "long" are 32-bit wide.
+
++ Added file= and data= keyword arguments to PhotoImage and BitmapImage.
+ This allows you to use them as drop-in replacements for the corre-
+ sponding Tkinter classes.
+
++ Removed bogus references to the crack coder (ImagingCrack).
+
+(0.3a1 released)
+
++ Make sure image is loaded in "tostring".
+
++ Added floating point packer (native 32-bit floats only).
+
+*** Changes from release 0.1b1 to 0.2 (b5) ***
+
++ Modified "fromstring" and "tostring" methods to use file codecs.
+ Also added "fromstring" factory method to create an image directly
+ from data in a string.
+
++ Added support for 32-bit floating point images (mode "F"). You
+ can convert between "L" and "F" images, and apply a subset of the
+ available image processing methods on the "F" image. You can also
+ read virtually any data format into a floating point image memory;
+ see the section on "Decoding Floating Point Data" in the handbook
+ for more information.
+
+(0.2b5 released; on windows only)
+
++ Fixed the tobitmap() method to work properly for small bitmaps.
+
++ Added RMS and standard deviation to the ImageStat.Stat class. Also
+ modified the constructor to take an optional feature mask, and also
+ to accept either an image or a list containing the histogram data.
+
++ The BitmapImage code in ImageTk can now use a special bitmap
+ decoder, which has to be patched into Tk. See the "Tk/pilbitmap.txt"
+ file for details. If not installed, bitmaps are transferred to Tk as
+ XBM strings.
+
++ The PhotoImage code in ImageTk now uses a Tcl command ("PyImagingPaste")
+ instead of a special image type. This gives somewhat better performance,
+ and also allows PIL to support transparency.
+ *** WARNING: TKAPPINIT MUST BE MODIFIED ***
+
++ ImageTk now honours the alpha layer in RGBA images. Only fully
+ transparent pixels are made transparent (that is, the alpha layer
+ is treated as a mask). To treat the alpha laters as a matte, you
+ must paste the image on the background before handing it over to
+ ImageTk.
+
++ Added McIdas reader (supports 8-bit images only).
+
++ PIL now preloads drivers for BMP, GIF, JPEG, PPM, and TIFF. As
+ long as you only load and save these formats, you don't have to
+ wait for a full scan for drivers. To force scanning, call the
+ Image.init() function.
+
++ The "seek" and "tell" methods are now always available, also for
+ single-frame images.
+
++ Added optional mask argument to histogram method. The mask may
+ be an "1" or "L" image with the same size as the original image.
+ Only pixels where the mask is non-zero are included in the
+ histogram.
+
++ The "paste" method now allows you to specify only the lower left
+ corner (a 2-tuple), instead of the full region (a 4-tuple).
+
++ Reverted to old plugin scanning model; now scans all directory
+ names in the path when looking for plugins.
+
++ Added PIXAR raster support. Only uncompressed ("dumped") RGB
+ images can currently be read (based on information provided
+ by Greg Coats).
+
++ Added FlashPix (FPX) read support. Reads all pixel formats, but
+ only the highest resolution is read, and the viewing transform is
+ currently ignored.
+
++ Made PNG encoding somewhat more efficient in "optimize" mode; a
+ bug in 0.2b4 didn't enable all predictor filters when optimized
+ storage were requested.
+
++ Added Microsoft Image Composer (MIC) read support. When opened,
+ the first sprite in the file is loaded. You can use the seek method
+ to load additional sprites from the file.
+
++ Properly reads "P" and "CMYK" PSD images.
+
++ "pilconvert" no longer optimizes by default; use the -o option to
+ make the file as small as possible (at the expense of speed); use
+ the -q option to set the quality when compressing to JPEG.
+
++ Fixed "crop" not to drop the palette for "P" images.
+
++ Added and verified FLC support.
+
++ Paste with "L" or "RGBA" alpha is now several times faster on most
+ platforms.
+
++ Changed Image.new() to initialize the image to black, as described
+ in the handbook. To get an uninitialized image, use None as the
+ colour.
+
++ Fixed the PDF encoder to produce a valid header; Acrobat no longer
+ complains when you load PDF images created by PIL.
+
++ PIL only scans fully-qualified directory names in the path when
+ looking for plugins.
+ *** WARNING: MAY BREAK EXISTING CODE ***
+
++ Faster implementation of "save" used when filename is given,
+ or when file object has "fileno" and "flush" methods.
+
++ Don't crash in "crop" if region extends outside the source image.
+
++ Eliminated a massive memory leak in the "save" function.
+
++ The GIF decoder doesn't crash if the code size is set to an illegal
+ value. This could happen since another bug didn't handle local
+ palettes properly if they didn't have the same size as the
+ global palette (not very common).
+
++ Added predictor support (TIFF 6.0 section 14) to the TIFF decoder.
+
++ Fixed palette and padding problems in BMP driver. Now properly
+ writes "1", "L", "P" and "RGB" images.
+
++ Fixed getpixel()/getdata() to return correct pixel values.
+
++ Added PSD (PhotoShop) read support. Reads both uncompressed
+ and compressed images of most types.
+
++ Added GIF write support (writes "uncompressed" GIF files only,
+ due to unresolvable licensing issues). The "gifmaker.py" script
+ can be used to create GIF animations.
+
++ Reads 8-bit "L" and "P" TGA images. Also reads 16-bit "RGB"
+ images.
+
++ Added FLI read support. This driver has only been tested
+ on a few FLI samples.
+
++ Reads 2-bit and 4-bit PCX images.
+
++ Added MSP read and write support. Both version 1 and 2 can be
+ read, but only version 1 (uncompressed) files are written.
+
++ Fixed a bug in the FLI/FLC identification code that caused the
+ driver to raise an exception when parsing valid FLI/FLC files.
+
++ Improved performance when loading file format plugins, and when
+ opening files.
+
++ Added GIF animation support, via the "seek" and "tell" methods.
+ You can use "player.py" to play an animated GIF file.
+
++ Removed MNG support, since the spec is changing faster than I
+ can change the code. I've added support for the experimental
+ ARG format instead. Contact me for more information on this
+ format.
+
++ Added keyword options to the "save" method. The following options
+ are currently supported:
+
+ format option description
+ --------------------------------------------------------
+ JPEG optimize minimize output file at the
+ expense of compression speed.
+
+ JPEG progressive enable progressive output. the
+ option value is ignored.
+
+ JPEG quality set compression quality (1-100).
+ the default value is 75.
+
+ JPEG smooth smooth dithered images. value
+ is strengh (1-100). default is
+ off (0).
+
+ PNG optimize minimize output file at the
+ expense of compression speed.
+
+ Expect more options in future releases. Also note that
+ file writers silently ignore unknown options.
+
++ Plugged memory leaks in the PNG and TIFF decoders.
+
++ Added PNG write support.
+
++ (internal) RGB unpackers and converters now set the pad byte
+ to 255 (full opacity).
+
++ Properly handles the "transparency" property for GIF, PNG
+ and XPM files.
+
++ Added a "putalpha" method, allowing you to attach a "1" or "L"
+ image as the alpha layer to an "RGBA" image.
+
++ Various improvements to the sample scripts:
+
+ "pilconvert" Carries out some extra tricks in order to make
+ the resulting file as small as possible.
+
+ "explode" (NEW) Split an image sequence into individual frames.
+
+ "gifmaker" (NEW) Convert a sequence file into a GIF animation.
+ Note that the GIF encoder create "uncompressed" GIF
+ files, so animations created by this script are
+ rather large (typically 2-5 times the compressed
+ sizes).
+
+ "image2py" (NEW) Convert a single image to a python module. See
+ comments in this script for details.
+
+ "player" If multiple images are given on the command line,
+ they are interpreted as frames in a sequence. The
+ script assumes that they all have the same size.
+ Also note that this script now can play FLI/FLC
+ and GIF animations.
+
+ This player can also execute embedded Python
+ animation applets (ARG format only).
+
+ "viewer" Transparent images ("P" with transparency property,
+ and "RGBA") are superimposed on the standard Tk back-
+ ground.
+
++ Fixed colour argument to "new". For multilayer images, pass a
+ tuple: (Red, Green, Blue), (Red, Green, Blue, Alpha), or (Cyan,
+ Magenta, Yellow, Black).
+
++ Added XPM (X pixmap) read support.
+
+(0.2b3 released)
+
++ Added MNG (multi-image network graphics) read support. "Ming"
+ is a proposed animation standard, based on the PNG file format.
+
+ You can use the "player" sample script to display some flavours
+ of this format. The MNG standard is still under development,
+ as is this driver. More information, including sample files,
+ can be found at <ftp://swrinde.nde.swri.edu/pub/mng>
+
++ Added a "verify" method to images loaded from file. This method
+ scans the file for errors, without actually decoding the image
+ data, and raises a suitable exception if it finds any problems.
+ Currently implemented for PNG and MNG files only.
+
++ Added support for interlaced GIF images.
+
++ Added PNG read support -- if linked with the ZLIB compression library,
+ PIL reads all kinds of PNG images, except interlaced files.
+
++ Improved PNG identification support -- doesn't mess up on unknown
+ chunks, identifies all possible PNG modes, and verifies checksum
+ on PNG header chunks.
+
++ Added an experimental reader for placable Windows Meta Files (WMF).
+ This reader is still very incomplete, but it illustrates how PIL's
+ drawing capabilities can be used to render vector and metafile
+ formats.
+
++ Added restricted drivers for images from Image Tools (greyscale
+ only) and LabEye/IFUNC (common interchange modes only).
+
++ Some minor improvements to the sample scripts provided in the
+ "Scripts" directory.
+
++ The test images have been moved to the "Images" directory.
+
+(0.2b2 released)
+(0.2b1 released; Windows only)
+
++ Fixed filling of complex polygons. The ImageDraw "line" and
+ "polygon" methods also accept Path objects.
+
++ The ImageTk "PhotoImage" object can now be constructed directly
+ from an image. You can also pass the object itself to Tkinter,
+ instead of using the "image" attribute. Finally, using "paste"
+ on a displayed image automatically updates the display.
+
++ The ImageTk "BitmapImage" object allows you to create transparent
+ overlays from 1-bit images. You can pass the object itself to
+ Tkinter. The constructor takes the same arguments as the Tkinter
+ BitmapImage class; use the "foreground" option to set the colour
+ of the overlay.
+
++ Added a "putdata" method to the Image class. This can be used to
+ load a 1-layer image with data from a sequence object or a string.
+ An optional floating point scale and offset can be used to adjust
+ the data to fit into the 8-bit pixel range. Also see the "getdata"
+ method.
+
++ Added the EXTENT method to the Image "transform" method. This can
+ be used to quickly crop, stretch, shrink, or mirror a subregion
+ from another image.
+
++ Adapted to Python 1.4.
+
++ Added a project makefile for Visual C++ 4.x. This allows you to
+ easily build a dynamically linked version of PIL for Windows 95
+ and NT.
+
++ A Tk "booster" patch for Windows is available. It gives dramatic
+ performance improvements for some displays. Has been tested with
+ Tk 4.2 only, but is likely to work with Tk 4.1 as well. See the Tk
+ subdirectory for details.
+
++ You can now save 1-bit images in the XBM format. In addition, the
+ Image class now provides a "tobitmap" method which returns a string
+ containing an XBM representation of the image. Quite handy to use
+ with Tk.
+
++ More conversions, including "RGB" to "1" and more.
+
+(0.2a1 released)
+
++ Where earlier versions accepted lists, this version accepts arbitrary
+ Python sequences (including strings, in some cases). A few resource
+ leaks were plugged in the process.
+
++ The Image "paste" method now allows the box to extend outside
+ the target image. The size of the box, the image to be pasted,
+ and the optional mask must still match.
+
++ The ImageDraw module now supports filled polygons, outlined and
+ filled ellipses, and text. Font support is rudimentary, though.
+
++ The Image "point" method now takes an optional mode argument,
+ allowing you to convert the image while translating it. Currently,
+ this can only be used to convert "L" or "P" images to "1" images
+ (creating thresholded images or "matte" masks).
+
++ An Image "getpixel" method has been added. For single band images,
+ it returns the pixel value at a given position as an integer.
+ For n-band images, it returns an n-tuple of integers.
+
++ An Image "getdata" method has been added. It returns a sequence
+ object representing the image as a 1-dimensional array. Only len()
+ and [] can be used with this sequence. This method returns a
+ reference to the existing image data, so changes in the image
+ will be immediately reflected in the sequence object.
+
++ Fixed alignment problems in the Windows BMP writer.
+
++ If converting an "RGB" image to "RGB" or "L", you can give a second
+ argument containing a colour conversion matrix.
+
++ An Image "getbbox" method has been added. It returns the bounding
+ box of data in an image, considering the value 0 as background.
+
++ An Image "offset" method has been added. It returns a new image
+ where the contents of the image have been offset the given distance
+ in X and/or Y direction. Data wraps between edges.
+
++ Saves PDF images. The driver creates a binary PDF 1.1 files, using
+ JPEG compression for "L", "RGB", and "CMYK" images, and hex encoding
+ (same as for PostScript) for other formats.
+
++ The "paste" method now accepts "1" masks. Zero means transparent,
+ any other pixel value means opaque. This is faster than using an
+ "L" transparency mask.
+
++ Properly writes EPS files (and properly prints images to postscript
+ printers as well).
+
++ Reads 4-bit BMP files, as well as 4 and 8-bit Windows ICO and CUR
+ files. Cursor animations are not supported.
+
++ Fixed alignment problems in the Sun raster loader.
+
++ Added "draft" and "thumbnail" methods. The draft method is used
+ to optimize loading of JPEG and PCD files, the thumbnail method is
+ used to create a thumbnail representation of an image.
+
++ Added Windows display support, via the ImageWin class (see the
+ handbook for details).
+
++ Added raster conversion for EPS files. This requires GNU or Aladdin
+ Ghostscript, and probably works on UNIX only.
+
++ Reads PhotoCD (PCD) images. The base resolution (768x512) can be
+ read from a PhotoCD file.
+
++ Eliminated some compiler warnings. Bindings now compile cleanly in C++
+ mode. Note that the Imaging library itself must be compiled in C mode.
+
++ Added "bdf2pil.py", which converts BDF fonts into images with associated
+ metrics. This is definitely work in progress. For info, see description
+ in script for details.
+
++ Fixed a bug in the "ImageEnhance.py" module.
+
++ Fixed a bug in the netpbm save hack in "GifImagePlugin.py"
+
++ Fixed 90 and 270 degree rotation of rectangular images.
+
++ Properly reads 8-bit TIFF palette-color images.
+
++ Reads plane separated RGB and CMYK TIFF images.
+
++ Added driver debug mode. This is enabled by setting Image.DEBUG
+ to a non-zero value. Try the -D option to "pilfile.py" and see what
+ happens.
+
++ Don't crash on "atend" constructs in PostScript files.
+
++ Only the Image module imports _imaging directly. Other modules
+ should refer to the binding module as "Image.core".
+
+*** Changes from release 0.0 to 0.1 (b1) ***
+
++ A handbook is available (distributed separately).
+
++ The coordinate system is changed so that (0,0) is now located
+ in the upper left corner. This is in compliancy with ISO 12087
+ and 90% of all other image processing and graphics libraries.
+
++ Modes "1" (bilevel) and "P" (palette) have been introduced. Note
+ that bilevel images are stored with one byte per pixel.
+
++ The Image "crop" and "paste" methods now accepts None as the
+ box argument, to refer to the full image (self, that is).
+
++ The Image "crop" method now works properly.
+
++ The Image "point" method is now available. You can use either a
+ lookup table or a function taking one argument.
+
++ The Image join function has been renamed to "merge".
+
++ An Image "composite" function has been added. It is identical
+ to copy() followed by paste(mask).
+
++ An Image "eval" function has been added. It is currently identical
+ to point(function); that is, only a single image can be processed.
+
++ A set of channel operations has been added. See the "ImageChops"
+ module, test_chops.py, and the handbook for details.
+
++ Added the "pilconvert" utility, which converts image files. Note
+ that the number of output formats are still quite restricted.
+
++ Added the "pilfile" utility, which quickly identifies image files
+ (without loading them, in most cases).
+
++ Added the "pilprint" utility, which prints image files to Postscript
+ printers.
+
++ Added a rudimentary version of the "pilview" utility, which is
+ simple image viewer based on Tk. Only File/Exit and Image/Next
+ works properly.
+
++ An interface to Tk has been added. See "Lib/ImageTk.py" and README
+ for details.
+
++ An interface to Jack Jansen's Img library has been added (thanks to
+ Jack). This allows you to read images through the Img extensions file
+ format handlers. See the file "Lib/ImgExtImagePlugin.py" for details.
+
++ Postscript printing is provided through the PSDraw module. See the
+ handbook for details.
diff --git a/Imaging/CONTENTS b/Imaging/CONTENTS
new file mode 100644
index 0000000..171fe14
--- /dev/null
+++ b/Imaging/CONTENTS
@@ -0,0 +1,295 @@
+Imaging/README
+
+Imaging/CHANGES
+
+Imaging/CONTENTS
+Imaging/MANIFEST
+
+Imaging/BUILDME
+
+Imaging/setup.py
+
+Imaging/selftest.py
+Imaging/doctest.py
+
+Imaging/libImaging/Imaging.h
+Imaging/libImaging/ImDib.h
+Imaging/libImaging/ImPlatform.h
+
+Imaging/libImaging/Quant.h
+Imaging/libImaging/QuantHash.h
+Imaging/libImaging/QuantHeap.h
+Imaging/libImaging/QuantDefines.h
+Imaging/libImaging/QuantTypes.h
+
+Imaging/libImaging/Access.c
+Imaging/libImaging/Antialias.c
+Imaging/libImaging/Bands.c
+Imaging/libImaging/Blend.c
+Imaging/libImaging/Chops.c
+Imaging/libImaging/Convert.c
+Imaging/libImaging/ConvertYCbCr.c
+Imaging/libImaging/Copy.c
+Imaging/libImaging/Crc32.c
+Imaging/libImaging/Crop.c
+Imaging/libImaging/Dib.c
+Imaging/libImaging/Draw.c
+Imaging/libImaging/Effects.c
+Imaging/libImaging/Except.c
+Imaging/libImaging/File.c
+Imaging/libImaging/Fill.c
+Imaging/libImaging/Filter.c
+Imaging/libImaging/Geometry.c
+Imaging/libImaging/GetBBox.c
+Imaging/libImaging/Histo.c
+Imaging/libImaging/Matrix.c
+Imaging/libImaging/ModeFilter.c
+Imaging/libImaging/Negative.c
+Imaging/libImaging/Offset.c
+Imaging/libImaging/Pack.c
+Imaging/libImaging/Palette.c
+Imaging/libImaging/Paste.c
+Imaging/libImaging/Point.c
+Imaging/libImaging/Quant.c
+Imaging/libImaging/QuantHash.c
+Imaging/libImaging/QuantHeap.c
+Imaging/libImaging/RankFilter.c
+Imaging/libImaging/Storage.c
+Imaging/libImaging/Unpack.c
+Imaging/libImaging/UnpackYCC.c
+
+Imaging/libImaging/Bit.h
+Imaging/libImaging/Gif.h
+Imaging/libImaging/Jpeg.h
+Imaging/libImaging/Lzw.h
+Imaging/libImaging/Raw.h
+Imaging/libImaging/Zip.h
+Imaging/libImaging/BitDecode.c
+Imaging/libImaging/EpsEncode.c
+Imaging/libImaging/FliDecode.c
+Imaging/libImaging/GifDecode.c
+Imaging/libImaging/GifEncode.c
+Imaging/libImaging/HexDecode.c
+Imaging/libImaging/JpegDecode.c
+Imaging/libImaging/JpegEncode.c
+Imaging/libImaging/LzwDecode.c
+Imaging/libImaging/MspDecode.c
+Imaging/libImaging/PackDecode.c
+Imaging/libImaging/PcdDecode.c
+Imaging/libImaging/PcxEncode.c
+Imaging/libImaging/PcxDecode.c
+Imaging/libImaging/RawDecode.c
+Imaging/libImaging/RawEncode.c
+Imaging/libImaging/SunRleDecode.c
+Imaging/libImaging/TgaRleDecode.c
+Imaging/libImaging/XbmDecode.c
+Imaging/libImaging/XbmEncode.c
+Imaging/libImaging/ZipDecode.c
+Imaging/libImaging/ZipEncode.c
+
+Imaging/_imaging.c
+Imaging/decode.c
+Imaging/encode.c
+Imaging/display.c
+Imaging/map.c
+Imaging/outline.c
+Imaging/path.c
+
+Imaging/_imagingtk.c
+Imaging/_imagingft.c
+Imaging/_imagingmath.c
+
+Imaging/PIL.pth
+Imaging/PIL/__init__.py
+Imaging/PIL/ArgImagePlugin.py
+Imaging/PIL/BdfFontFile.py
+Imaging/PIL/BmpImagePlugin.py
+Imaging/PIL/BufrStubImagePlugin.py
+Imaging/PIL/ContainerIO.py
+Imaging/PIL/CurImagePlugin.py
+Imaging/PIL/DcxImagePlugin.py
+Imaging/PIL/EpsImagePlugin.py
+Imaging/PIL/ExifTags.py
+Imaging/PIL/FitsStubImagePlugin.py
+Imaging/PIL/FliImagePlugin.py
+Imaging/PIL/FontFile.py
+Imaging/PIL/FpxImagePlugin.py
+Imaging/PIL/GbrImagePlugin.py
+Imaging/PIL/GdImageFile.py
+Imaging/PIL/GifImagePlugin.py
+Imaging/PIL/GimpGradientFile.py
+Imaging/PIL/GimpPaletteFile.py
+Imaging/PIL/GribStubImagePlugin.py
+Imaging/PIL/Hdf5StubImagePlugin.py
+Imaging/PIL/IcoImagePlugin.py
+Imaging/PIL/IcnsImagePlugin.py
+Imaging/PIL/Image.py
+Imaging/PIL/ImageChops.py
+Imaging/PIL/ImageColor.py
+Imaging/PIL/ImageDraw.py
+Imaging/PIL/ImageDraw2.py
+Imaging/PIL/ImageEnhance.py
+Imaging/PIL/ImageFile.py
+Imaging/PIL/ImageFileIO.py
+Imaging/PIL/ImageFilter.py
+Imaging/PIL/ImageFont.py
+Imaging/PIL/ImageGL.py
+Imaging/PIL/ImageGrab.py
+Imaging/PIL/ImageMath.py
+Imaging/PIL/ImageMode.py
+Imaging/PIL/ImageOps.py
+Imaging/PIL/ImagePalette.py
+Imaging/PIL/ImagePath.py
+Imaging/PIL/ImageQt.py
+Imaging/PIL/ImageSequence.py
+Imaging/PIL/ImageStat.py
+Imaging/PIL/ImageTk.py
+Imaging/PIL/ImageTransform.py
+Imaging/PIL/ImageWin.py
+Imaging/PIL/ImImagePlugin.py
+Imaging/PIL/ImtImagePlugin.py
+Imaging/PIL/IptcImagePlugin.py
+Imaging/PIL/JpegImagePlugin.py
+Imaging/PIL/McIdasImagePlugin.py
+Imaging/PIL/MicImagePlugin.py
+Imaging/PIL/MpegImagePlugin.py
+Imaging/PIL/MspImagePlugin.py
+Imaging/PIL/OleFileIO.py
+Imaging/PIL/PaletteFile.py
+Imaging/PIL/PalmImagePlugin.py
+Imaging/PIL/PcdImagePlugin.py
+Imaging/PIL/PcfFontFile.py
+Imaging/PIL/PcxImagePlugin.py
+Imaging/PIL/PdfImagePlugin.py
+Imaging/PIL/PixarImagePlugin.py
+Imaging/PIL/PngImagePlugin.py
+Imaging/PIL/PpmImagePlugin.py
+Imaging/PIL/PsdImagePlugin.py
+Imaging/PIL/PSDraw.py
+Imaging/PIL/SgiImagePlugin.py
+Imaging/PIL/SpiderImagePlugin.py
+Imaging/PIL/SunImagePlugin.py
+Imaging/PIL/TarIO.py
+Imaging/PIL/TgaImagePlugin.py
+Imaging/PIL/TiffImagePlugin.py
+Imaging/PIL/TiffTags.py
+Imaging/PIL/WalImageFile.py
+Imaging/PIL/WmfImagePlugin.py
+Imaging/PIL/XbmImagePlugin.py
+Imaging/PIL/XpmImagePlugin.py
+Imaging/PIL/XVThumbImagePlugin.py
+
+Imaging/Docs/index.html
+Imaging/Docs/effbot.css
+Imaging/Docs/pythondoc-PIL.ArgImagePlugin.html
+Imaging/Docs/pythondoc-PIL.BdfFontFile.html
+Imaging/Docs/pythondoc-PIL.BmpImagePlugin.html
+Imaging/Docs/pythondoc-PIL.BufrStubImagePlugin.html
+Imaging/Docs/pythondoc-PIL.ContainerIO.html
+Imaging/Docs/pythondoc-PIL.CurImagePlugin.html
+Imaging/Docs/pythondoc-PIL.DcxImagePlugin.html
+Imaging/Docs/pythondoc-PIL.EpsImagePlugin.html
+Imaging/Docs/pythondoc-PIL.ExifTags.html
+Imaging/Docs/pythondoc-PIL.FitsStubImagePlugin.html
+Imaging/Docs/pythondoc-PIL.FliImagePlugin.html
+Imaging/Docs/pythondoc-PIL.FontFile.html
+Imaging/Docs/pythondoc-PIL.FpxImagePlugin.html
+Imaging/Docs/pythondoc-PIL.GbrImagePlugin.html
+Imaging/Docs/pythondoc-PIL.GdImageFile.html
+Imaging/Docs/pythondoc-PIL.GifImagePlugin.html
+Imaging/Docs/pythondoc-PIL.GimpGradientFile.html
+Imaging/Docs/pythondoc-PIL.GimpPaletteFile.html
+Imaging/Docs/pythondoc-PIL.GribStubImagePlugin.html
+Imaging/Docs/pythondoc-PIL.Hdf5StubImagePlugin.html
+Imaging/Docs/pythondoc-PIL.IcoImagePlugin.html
+Imaging/Docs/pythondoc-PIL.IcnsImagePlugin.html
+Imaging/Docs/pythondoc-PIL.Image.html
+Imaging/Docs/pythondoc-PIL.ImageChops.html
+Imaging/Docs/pythondoc-PIL.ImageColor.html
+Imaging/Docs/pythondoc-PIL.ImageDraw.html
+Imaging/Docs/pythondoc-PIL.ImageEnhance.html
+Imaging/Docs/pythondoc-PIL.ImageFile.html
+Imaging/Docs/pythondoc-PIL.ImageFileIO.html
+Imaging/Docs/pythondoc-PIL.ImageFilter.html
+Imaging/Docs/pythondoc-PIL.ImageFont.html
+Imaging/Docs/pythondoc-PIL.ImageGL.html
+Imaging/Docs/pythondoc-PIL.ImageGrab.html
+Imaging/Docs/pythondoc-PIL.ImageOps.html
+Imaging/Docs/pythondoc-PIL.ImagePalette.html
+Imaging/Docs/pythondoc-PIL.ImagePath.html
+Imaging/Docs/pythondoc-PIL.ImageSequence.html
+Imaging/Docs/pythondoc-PIL.ImageStat.html
+Imaging/Docs/pythondoc-PIL.ImageTk.html
+Imaging/Docs/pythondoc-PIL.ImageTransform.html
+Imaging/Docs/pythondoc-PIL.ImageWin.html
+Imaging/Docs/pythondoc-PIL.ImImagePlugin.html
+Imaging/Docs/pythondoc-PIL.ImtImagePlugin.html
+Imaging/Docs/pythondoc-PIL.IptcImagePlugin.html
+Imaging/Docs/pythondoc-PIL.JpegImagePlugin.html
+Imaging/Docs/pythondoc-PIL.McIdasImagePlugin.html
+Imaging/Docs/pythondoc-PIL.MicImagePlugin.html
+Imaging/Docs/pythondoc-PIL.MpegImagePlugin.html
+Imaging/Docs/pythondoc-PIL.MspImagePlugin.html
+Imaging/Docs/pythondoc-PIL.OleFileIO.html
+Imaging/Docs/pythondoc-PIL.PaletteFile.html
+Imaging/Docs/pythondoc-PIL.PalmImagePlugin.html
+Imaging/Docs/pythondoc-PIL.PcdImagePlugin.html
+Imaging/Docs/pythondoc-PIL.PcfFontFile.html
+Imaging/Docs/pythondoc-PIL.PcxImagePlugin.html
+Imaging/Docs/pythondoc-PIL.PdfImagePlugin.html
+Imaging/Docs/pythondoc-PIL.PixarImagePlugin.html
+Imaging/Docs/pythondoc-PIL.PngImagePlugin.html
+Imaging/Docs/pythondoc-PIL.PpmImagePlugin.html
+Imaging/Docs/pythondoc-PIL.PsdImagePlugin.html
+Imaging/Docs/pythondoc-PIL.PSDraw.html
+Imaging/Docs/pythondoc-PIL.SgiImagePlugin.html
+Imaging/Docs/pythondoc-PIL.SpiderImagePlugin.html
+Imaging/Docs/pythondoc-PIL.SunImagePlugin.html
+Imaging/Docs/pythondoc-PIL.TarIO.html
+Imaging/Docs/pythondoc-PIL.TgaImagePlugin.html
+Imaging/Docs/pythondoc-PIL.TiffImagePlugin.html
+Imaging/Docs/pythondoc-PIL.TiffTags.html
+Imaging/Docs/pythondoc-PIL.WalImageFile.html
+Imaging/Docs/pythondoc-PIL.WmfImagePlugin.html
+Imaging/Docs/pythondoc-PIL.XbmImagePlugin.html
+Imaging/Docs/pythondoc-PIL.XpmImagePlugin.html
+Imaging/Docs/pythondoc-PIL.XVThumbImagePlugin.html
+
+Imaging/Scripts/pilconvert.py
+Imaging/Scripts/pildriver.py
+Imaging/Scripts/pilfile.py
+Imaging/Scripts/pilfont.py
+Imaging/Scripts/pilprint.py
+
+Imaging/Images/lena.gif
+Imaging/Images/lena.ppm
+Imaging/Images/lena.jpg
+
+Imaging/Images/courB08.bdf
+Imaging/Images/courB08.pbm
+Imaging/Images/courB08.pil
+
+Imaging/Sane/README
+Imaging/Sane/CHANGES
+Imaging/Sane/setup.py
+Imaging/Sane/sanedoc.txt
+Imaging/Sane/_sane.c
+Imaging/Sane/sane.py
+Imaging/Sane/demo_numarray.py
+Imaging/Sane/demo_pil.py
+
+Imaging/Scripts/README
+Imaging/Scripts/enhancer.py
+Imaging/Scripts/explode.py
+Imaging/Scripts/gifmaker.py
+Imaging/Scripts/image2py.py
+Imaging/Scripts/painter.py
+Imaging/Scripts/player.py
+Imaging/Scripts/viewer.py
+Imaging/Scripts/thresholder.py
+
+Imaging/Tk/tkImaging.c
+Imaging/Tk/install.txt
+Imaging/Tk/booster.txt
+Imaging/Tk/pilbitmap.txt
+
diff --git a/Imaging/Docs/effbot.css b/Imaging/Docs/effbot.css
new file mode 100644
index 0000000..d137735
--- /dev/null
+++ b/Imaging/Docs/effbot.css
@@ -0,0 +1,118 @@
+/* effbot.css */
+
+BODY {
+ font: 100% Georgia, Times, serif;
+ color: black;
+ margin: 0px 20px 0px 20px;
+}
+
+#effbot-body {
+ background: white;
+ padding: 10px 40px 10px 40px;
+ max-width: 50em;
+}
+
+#effbot-menu {
+ display: none;
+}
+
+.adsense {
+ background: #f8fff8;
+ border: 1px solid #084;
+ padding: 10px 4px 4px 4px;
+}
+
+.sidebar {
+ border: 1px solid #000;
+ float: right; clear: right;
+ width: 200px;
+ background: white;
+ padding: 10px;
+ margin: 0px -25px 10px 0px;
+}
+
+/* visual style */
+
+P {
+ line-height: 1.3em;
+}
+
+CODE, PRE {
+ font: 100% "Courier New", Courier, Monaco, monospace;
+ color: #042; margin-left: 20px;
+}
+
+H1, H2, H3 {
+ font-family: Georgia, Times, serif;
+ color: #084; margin-top: 30px;
+}
+
+H1, H2, { border-top: 1px solid #084; }
+
+H4, H5, H6 {
+ font-family: Georgia, Times, serif;
+ color: #084; margin-top: 15px;
+}
+
+A:link, A:hover { color: #084; }
+A:visited { color: #404040; }
+
+UL LI { list-style-type: square; }
+
+.title { margin-bottom: 2px; color: #084; }
+.info { font-size: 80%; color: #084; margin-top: 0px; }
+
+.bluebox { color: #084; margin-top: 10px; }
+
+.highlight { background: #cfc; }
+.mark { color: #084; }
+.small { font-size: 80%; }
+.display { background: #eee; padding: 20px; }
+
+.note {
+ background: #efe;
+ border-top: 1px solid #084;
+ border-bottom: 1px solid #084;
+ padding: 2px 20px;
+}
+
+.example {
+ border-top: medium solid #084;
+ border-bottom: medium solid #084;
+ padding: 5px;
+}
+
+.figure {
+ border-top: medium solid #084;
+ border-bottom: medium solid #084;
+ padding: 5px;
+}
+
+.fixme {
+ background: #eee;
+ border: 1px solid #084;
+ padding: 2x 20px;
+}
+
+.simpletable {
+ border: 1px solid #084;
+ border-collapse: collapse;
+}
+
+.simpletable TH {
+ text-align: left;
+ background: #cfc;
+ border: 1px solid #084;
+ margin: 0px;
+ padding: 1px 5px;
+}
+
+.simpletable TD {
+ border: 1px solid #084;
+ margin: 0px;
+ padding: 5px;
+}
+
+/* xmldiff markup */
+.new { text-decoration: underline; color: red; background: #fff0f0; }
+.old { text-decoration: line-through; color: blue; background: #f0f0ff; }
diff --git a/Imaging/Docs/index.html b/Imaging/Docs/index.html
new file mode 100644
index 0000000..fbc76a9
--- /dev/null
+++ b/Imaging/Docs/index.html
@@ -0,0 +1,103 @@
+
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The Python Imaging Library</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The Python Imaging Library</h1>
+
+<h3 id='online'>Online Resources</h3>
+
+<dl>
+<dt><a href='http://www.pythonware.com/products/pil'><i>Python Imaging Library</i></a> (official product page at <a href="http://www.pythonware.com">pythonware.com</a>)</dt>
+<dt><a href='http://effbot.org/zone/pil-index.htm'><i>Python Imaging Library</i></a> (development page at <a href="http://effbot.org">effbot.org</a>)</dt>
+</dl>
+
+<h3>Package Contents</h3>
+
+<p>The following pages are generated from <a href='http://effbot.org/zone/pythondoc.htm'><b>pythondoc</b></a> markup in the source files.</p>
+
+<dl>
+<dt><a href='pythondoc-PIL.Image.html'>The PIL.Image Module</a></dt>
+<dt><a href='pythondoc-PIL.ImageChops.html'>The PIL.ImageChops Module</a></dt>
+<dt><a href='pythondoc-PIL.ImageColor.html'>The PIL.ImageColor Module</a></dt>
+<dt><a href='pythondoc-PIL.ImageDraw.html'>The PIL.ImageDraw Module</a></dt>
+<dt><a href='pythondoc-PIL.ImageEnhance.html'>The PIL.ImageEnhance Module</a></dt>
+<dt><a href='pythondoc-PIL.ImageFile.html'>The PIL.ImageFile Module</a></dt>
+<dt><a href='pythondoc-PIL.ImageFileIO.html'>The PIL.ImageFileIO Module</a></dt>
+<dt><a href='pythondoc-PIL.ImageFilter.html'>The PIL.ImageFilter Module</a></dt>
+<dt><a href='pythondoc-PIL.ImageFont.html'>The PIL.ImageFont Module</a></dt>
+<dt><a href='pythondoc-PIL.ImageGL.html'>The PIL.ImageGL Module</a></dt>
+<dt><a href='pythondoc-PIL.ImageGrab.html'>The PIL.ImageGrab Module</a></dt>
+<dt><a href='pythondoc-PIL.ImageMath.html'>The PIL.ImageMath Module</a></dt>
+<dt><a href='pythondoc-PIL.ImageMode.html'>The PIL.ImageMode Module</a></dt>
+<dt><a href='pythondoc-PIL.ImageOps.html'>The PIL.ImageOps Module</a></dt>
+<dt><a href='pythondoc-PIL.ImagePalette.html'>The PIL.ImagePalette Module</a></dt>
+<dt><a href='pythondoc-PIL.ImagePath.html'>The PIL.ImagePath Module</a></dt>
+<dt><a href='pythondoc-PIL.ImageQt.html'>The PIL.ImageQt Module</a></dt>
+<dt><a href='pythondoc-PIL.ImageSequence.html'>The PIL.ImageSequence Module</a></dt>
+<dt><a href='pythondoc-PIL.ImageStat.html'>The PIL.ImageStat Module</a></dt>
+<dt><a href='pythondoc-PIL.ImageTk.html'>The PIL.ImageTk Module</a></dt>
+<dt><a href='pythondoc-PIL.ImageTransform.html'>The PIL.ImageTransform Module</a></dt>
+<dt><a href='pythondoc-PIL.ImageWin.html'>The PIL.ImageWin Module</a></dt>
+<dt>&nbsp;</dt>
+<dt><a href='pythondoc-PIL.ArgImagePlugin.html'>The PIL.ArgImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.BdfFontFile.html'>The PIL.BdfFontFile Module</a></dt>
+<dt><a href='pythondoc-PIL.BmpImagePlugin.html'>The PIL.BmpImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.BufrStubImagePlugin.html'>The PIL.BufrStubImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.ContainerIO.html'>The PIL.ContainerIO Module</a></dt>
+<dt><a href='pythondoc-PIL.CurImagePlugin.html'>The PIL.CurImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.DcxImagePlugin.html'>The PIL.DcxImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.EpsImagePlugin.html'>The PIL.EpsImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.ExifTags.html'>The PIL.ExifTags Module</a></dt>
+<dt><a href='pythondoc-PIL.FitsStubImagePlugin.html'>The PIL.FitsStubImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.FliImagePlugin.html'>The PIL.FliImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.FontFile.html'>The PIL.FontFile Module</a></dt>
+<dt><a href='pythondoc-PIL.FpxImagePlugin.html'>The PIL.FpxImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.GbrImagePlugin.html'>The PIL.GbrImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.GdImageFile.html'>The PIL.GdImageFile Module</a></dt>
+<dt><a href='pythondoc-PIL.GifImagePlugin.html'>The PIL.GifImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.GimpGradientFile.html'>The PIL.GimpGradientFile Module</a></dt>
+<dt><a href='pythondoc-PIL.GimpPaletteFile.html'>The PIL.GimpPaletteFile Module</a></dt>
+<dt><a href='pythondoc-PIL.GribStubImagePlugin.html'>The PIL.GribStubImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.Hdf5StubImagePlugin.html'>The PIL.Hdf5StubImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.IcnsImagePlugin.html'>The PIL.IcnsImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.IcoImagePlugin.html'>The PIL.IcoImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.ImImagePlugin.html'>The PIL.ImImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.ImtImagePlugin.html'>The PIL.ImtImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.IptcImagePlugin.html'>The PIL.IptcImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.JpegImagePlugin.html'>The PIL.JpegImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.McIdasImagePlugin.html'>The PIL.McIdasImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.MicImagePlugin.html'>The PIL.MicImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.MpegImagePlugin.html'>The PIL.MpegImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.MspImagePlugin.html'>The PIL.MspImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.OleFileIO.html'>The PIL.OleFileIO Module</a></dt>
+<dt><a href='pythondoc-PIL.PSDraw.html'>The PIL.PSDraw Module</a></dt>
+<dt><a href='pythondoc-PIL.PaletteFile.html'>The PIL.PaletteFile Module</a></dt>
+<dt><a href='pythondoc-PIL.PalmImagePlugin.html'>The PIL.PalmImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.PcdImagePlugin.html'>The PIL.PcdImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.PcfFontFile.html'>The PIL.PcfFontFile Module</a></dt>
+<dt><a href='pythondoc-PIL.PcxImagePlugin.html'>The PIL.PcxImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.PdfImagePlugin.html'>The PIL.PdfImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.PixarImagePlugin.html'>The PIL.PixarImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.PngImagePlugin.html'>The PIL.PngImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.PpmImagePlugin.html'>The PIL.PpmImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.PsdImagePlugin.html'>The PIL.PsdImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.SgiImagePlugin.html'>The PIL.SgiImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.SunImagePlugin.html'>The PIL.SunImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.TarIO.html'>The PIL.TarIO Module</a></dt>
+<dt><a href='pythondoc-PIL.TgaImagePlugin.html'>The PIL.TgaImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.TiffImagePlugin.html'>The PIL.TiffImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.TiffTags.html'>The PIL.TiffTags Module</a></dt>
+<dt><a href='pythondoc-PIL.WalImageFile.html'>The PIL.WalImageFile Module</a></dt>
+<dt><a href='pythondoc-PIL.WbmpImagePlugin.html'>The PIL.WbmpImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.WmfImagePlugin.html'>The PIL.WmfImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.XVThumbImagePlugin.html'>The PIL.XVThumbImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.XbmImagePlugin.html'>The PIL.XbmImagePlugin Module</a></dt>
+<dt><a href='pythondoc-PIL.XpmImagePlugin.html'>The PIL.XpmImagePlugin Module</a></dt>
+</dl>
+
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ArgImagePlugin.html b/Imaging/Docs/pythondoc-PIL.ArgImagePlugin.html
new file mode 100644
index 0000000..28aa4e1
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ArgImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ArgImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ArgImagePlugin Module</h1>
+<dl>
+<dt><b>ArgImageFile</b> (class) [<a href='#PIL.ArgImagePlugin.ArgImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for the experimental Animated Raster Graphics format.</p>
+<p>For more information about this class, see <a href='#PIL.ArgImagePlugin.ArgImageFile-class'><i>The ArgImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.ArgImagePlugin.ArgImageFile-class' name='PIL.ArgImagePlugin.ArgImageFile-class'>The ArgImageFile Class</a></h2>
+<dl>
+<dt><b>ArgImageFile</b> (class) [<a href='#PIL.ArgImagePlugin.ArgImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.BdfFontFile.html b/Imaging/Docs/pythondoc-PIL.BdfFontFile.html
new file mode 100644
index 0000000..1f2008c
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.BdfFontFile.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.BdfFontFile Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.BdfFontFile Module</h1>
+<dl>
+<dt><b>BdfFontFile(fp)</b> (class) [<a href='#PIL.BdfFontFile.BdfFontFile-class'>#</a>]</dt>
+<dd>
+<p>Font file plugin for the X11 BDF format.</p>
+<p>For more information about this class, see <a href='#PIL.BdfFontFile.BdfFontFile-class'><i>The BdfFontFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.BdfFontFile.BdfFontFile-class' name='PIL.BdfFontFile.BdfFontFile-class'>The BdfFontFile Class</a></h2>
+<dl>
+<dt><b>BdfFontFile(fp)</b> (class) [<a href='#PIL.BdfFontFile.BdfFontFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.BmpImagePlugin.html b/Imaging/Docs/pythondoc-PIL.BmpImagePlugin.html
new file mode 100644
index 0000000..17fe0d1
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.BmpImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.BmpImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.BmpImagePlugin Module</h1>
+<dl>
+<dt><b>BmpImageFile</b> (class) [<a href='#PIL.BmpImagePlugin.BmpImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for the Windows BMP format.</p>
+<p>For more information about this class, see <a href='#PIL.BmpImagePlugin.BmpImageFile-class'><i>The BmpImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.BmpImagePlugin.BmpImageFile-class' name='PIL.BmpImagePlugin.BmpImageFile-class'>The BmpImageFile Class</a></h2>
+<dl>
+<dt><b>BmpImageFile</b> (class) [<a href='#PIL.BmpImagePlugin.BmpImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.BufrStubImagePlugin.html b/Imaging/Docs/pythondoc-PIL.BufrStubImagePlugin.html
new file mode 100644
index 0000000..c17a119
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.BufrStubImagePlugin.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.BufrStubImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.BufrStubImagePlugin Module</h1>
+<dl>
+<dt><a id='PIL.BufrStubImagePlugin.register_handler-function' name='PIL.BufrStubImagePlugin.register_handler-function'><b>register_handler(handler)</b></a> [<a href='#PIL.BufrStubImagePlugin.register_handler-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>handler</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ContainerIO.html b/Imaging/Docs/pythondoc-PIL.ContainerIO.html
new file mode 100644
index 0000000..61e4c91
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ContainerIO.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ContainerIO Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ContainerIO Module</h1>
+<dl>
+<dt><b>ContainerIO(file, offset, length)</b> (class) [<a href='#PIL.ContainerIO.ContainerIO-class'>#</a>]</dt>
+<dd>
+<p>A file object that provides read access to a part of an existing
+file (for example a TAR file).</p>
+<p>For more information about this class, see <a href='#PIL.ContainerIO.ContainerIO-class'><i>The ContainerIO Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.ContainerIO.ContainerIO-class' name='PIL.ContainerIO.ContainerIO-class'>The ContainerIO Class</a></h2>
+<dl>
+<dt><b>ContainerIO(file, offset, length)</b> (class) [<a href='#PIL.ContainerIO.ContainerIO-class'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ContainerIO.ContainerIO.__init__-method' name='PIL.ContainerIO.ContainerIO.__init__-method'><b>__init__(file, offset, length)</b></a> [<a href='#PIL.ContainerIO.ContainerIO.__init__-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>file</i></dt>
+<dd>
+</dd>
+<dt><i>offset</i></dt>
+<dd>
+</dd>
+<dt><i>length</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ContainerIO.ContainerIO.isatty-method' name='PIL.ContainerIO.ContainerIO.isatty-method'><b>isatty()</b></a> [<a href='#PIL.ContainerIO.ContainerIO.isatty-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ContainerIO.ContainerIO.read-method' name='PIL.ContainerIO.ContainerIO.read-method'><b>read(bytes=0)</b></a> [<a href='#PIL.ContainerIO.ContainerIO.read-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>bytes</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ContainerIO.ContainerIO.readline-method' name='PIL.ContainerIO.ContainerIO.readline-method'><b>readline()</b></a> [<a href='#PIL.ContainerIO.ContainerIO.readline-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ContainerIO.ContainerIO.readlines-method' name='PIL.ContainerIO.ContainerIO.readlines-method'><b>readlines()</b></a> [<a href='#PIL.ContainerIO.ContainerIO.readlines-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ContainerIO.ContainerIO.seek-method' name='PIL.ContainerIO.ContainerIO.seek-method'><b>seek(offset, mode=0)</b></a> [<a href='#PIL.ContainerIO.ContainerIO.seek-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>offset</i></dt>
+<dd>
+</dd>
+<dt><i>mode</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ContainerIO.ContainerIO.tell-method' name='PIL.ContainerIO.ContainerIO.tell-method'><b>tell()</b></a> [<a href='#PIL.ContainerIO.ContainerIO.tell-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.CurImagePlugin.html b/Imaging/Docs/pythondoc-PIL.CurImagePlugin.html
new file mode 100644
index 0000000..0dafd34
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.CurImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.CurImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.CurImagePlugin Module</h1>
+<dl>
+<dt><b>CurImageFile</b> (class) [<a href='#PIL.CurImagePlugin.CurImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for Windows Cursor files.</p>
+<p>For more information about this class, see <a href='#PIL.CurImagePlugin.CurImageFile-class'><i>The CurImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.CurImagePlugin.CurImageFile-class' name='PIL.CurImagePlugin.CurImageFile-class'>The CurImageFile Class</a></h2>
+<dl>
+<dt><b>CurImageFile</b> (class) [<a href='#PIL.CurImagePlugin.CurImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.DcxImagePlugin.html b/Imaging/Docs/pythondoc-PIL.DcxImagePlugin.html
new file mode 100644
index 0000000..335ac43
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.DcxImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.DcxImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.DcxImagePlugin Module</h1>
+<dl>
+<dt><b>DcxImageFile</b> (class) [<a href='#PIL.DcxImagePlugin.DcxImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for the Intel DCX format.</p>
+<p>For more information about this class, see <a href='#PIL.DcxImagePlugin.DcxImageFile-class'><i>The DcxImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.DcxImagePlugin.DcxImageFile-class' name='PIL.DcxImagePlugin.DcxImageFile-class'>The DcxImageFile Class</a></h2>
+<dl>
+<dt><b>DcxImageFile</b> (class) [<a href='#PIL.DcxImagePlugin.DcxImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.EpsImagePlugin.html b/Imaging/Docs/pythondoc-PIL.EpsImagePlugin.html
new file mode 100644
index 0000000..262b346
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.EpsImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.EpsImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.EpsImagePlugin Module</h1>
+<dl>
+<dt><b>EpsImageFile</b> (class) [<a href='#PIL.EpsImagePlugin.EpsImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for Encapsulated Postscript.</p>
+<p>For more information about this class, see <a href='#PIL.EpsImagePlugin.EpsImageFile-class'><i>The EpsImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.EpsImagePlugin.EpsImageFile-class' name='PIL.EpsImagePlugin.EpsImageFile-class'>The EpsImageFile Class</a></h2>
+<dl>
+<dt><b>EpsImageFile</b> (class) [<a href='#PIL.EpsImagePlugin.EpsImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ExifTags.html b/Imaging/Docs/pythondoc-PIL.ExifTags.html
new file mode 100644
index 0000000..39aab43
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ExifTags.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ExifTags Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ExifTags Module</h1>
+<h2>Module Contents</h2>
+<dl>
+<dt><a id='PIL.ExifTags.GPSTAGS-variable' name='PIL.ExifTags.GPSTAGS-variable'><b>GPSTAGS</b></a> (variable) [<a href='#PIL.ExifTags.GPSTAGS-variable'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ExifTags.TAGS-variable' name='PIL.ExifTags.TAGS-variable'><b>TAGS</b></a> (variable) [<a href='#PIL.ExifTags.TAGS-variable'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.FitsStubImagePlugin.html b/Imaging/Docs/pythondoc-PIL.FitsStubImagePlugin.html
new file mode 100644
index 0000000..1492f74
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.FitsStubImagePlugin.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.FitsStubImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.FitsStubImagePlugin Module</h1>
+<dl>
+<dt><a id='PIL.FitsStubImagePlugin.register_handler-function' name='PIL.FitsStubImagePlugin.register_handler-function'><b>register_handler(handler)</b></a> [<a href='#PIL.FitsStubImagePlugin.register_handler-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>handler</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.FliImagePlugin.html b/Imaging/Docs/pythondoc-PIL.FliImagePlugin.html
new file mode 100644
index 0000000..0d7faa0
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.FliImagePlugin.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.FliImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.FliImagePlugin Module</h1>
+<dl>
+<dt><b>FliImageFile</b> (class) [<a href='#PIL.FliImagePlugin.FliImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for the FLI/FLC animation format.</p>
+<p>For more information about this class, see <a href='#PIL.FliImagePlugin.FliImageFile-class'><i>The FliImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.FliImagePlugin.FliImageFile-class' name='PIL.FliImagePlugin.FliImageFile-class'>The FliImageFile Class</a></h2>
+<dl>
+<dt><b>FliImageFile</b> (class) [<a href='#PIL.FliImagePlugin.FliImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for the FLI/FLC animation format. Use the <b>seek</b>
+method to load individual frames.
+</p></dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.FontFile.html b/Imaging/Docs/pythondoc-PIL.FontFile.html
new file mode 100644
index 0000000..7f9b82f
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.FontFile.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.FontFile Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.FontFile Module</h1>
+<dl>
+<dt><b>FontFile()</b> (class) [<a href='#PIL.FontFile.FontFile-class'>#</a>]</dt>
+<dd>
+<p>Base class for raster font file handlers.</p>
+<p>For more information about this class, see <a href='#PIL.FontFile.FontFile-class'><i>The FontFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.FontFile.FontFile-class' name='PIL.FontFile.FontFile-class'>The FontFile Class</a></h2>
+<dl>
+<dt><b>FontFile()</b> (class) [<a href='#PIL.FontFile.FontFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.FpxImagePlugin.html b/Imaging/Docs/pythondoc-PIL.FpxImagePlugin.html
new file mode 100644
index 0000000..f4631b8
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.FpxImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.FpxImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.FpxImagePlugin Module</h1>
+<dl>
+<dt><b>FpxImageFile</b> (class) [<a href='#PIL.FpxImagePlugin.FpxImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for the FlashPix images.</p>
+<p>For more information about this class, see <a href='#PIL.FpxImagePlugin.FpxImageFile-class'><i>The FpxImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.FpxImagePlugin.FpxImageFile-class' name='PIL.FpxImagePlugin.FpxImageFile-class'>The FpxImageFile Class</a></h2>
+<dl>
+<dt><b>FpxImageFile</b> (class) [<a href='#PIL.FpxImagePlugin.FpxImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.GbrImagePlugin.html b/Imaging/Docs/pythondoc-PIL.GbrImagePlugin.html
new file mode 100644
index 0000000..a318ed7
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.GbrImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.GbrImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.GbrImagePlugin Module</h1>
+<dl>
+<dt><b>GbrImageFile</b> (class) [<a href='#PIL.GbrImagePlugin.GbrImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for the GIMP brush format.</p>
+<p>For more information about this class, see <a href='#PIL.GbrImagePlugin.GbrImageFile-class'><i>The GbrImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.GbrImagePlugin.GbrImageFile-class' name='PIL.GbrImagePlugin.GbrImageFile-class'>The GbrImageFile Class</a></h2>
+<dl>
+<dt><b>GbrImageFile</b> (class) [<a href='#PIL.GbrImagePlugin.GbrImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.GdImageFile.html b/Imaging/Docs/pythondoc-PIL.GdImageFile.html
new file mode 100644
index 0000000..554ffb9
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.GdImageFile.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.GdImageFile Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.GdImageFile Module</h1>
+<dl>
+<dt><b>GdImageFile</b> (class) [<a href='#PIL.GdImageFile.GdImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for the GD uncompressed format.</p>
+<p>For more information about this class, see <a href='#PIL.GdImageFile.GdImageFile-class'><i>The GdImageFile Class</i></a>.</p>
+</dd>
+<dt><a id='PIL.GdImageFile.open-function' name='PIL.GdImageFile.open-function'><b>open(fp, mode=&quot;r&quot;)</b></a> [<a href='#PIL.GdImageFile.open-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>filename</i></dt>
+<dd>
+</dd>
+<dt><i>mode</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+<dt>Raises <b>IOError</b>:</dt><dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+<h2><a id='PIL.GdImageFile.GdImageFile-class' name='PIL.GdImageFile.GdImageFile-class'>The GdImageFile Class</a></h2>
+<dl>
+<dt><b>GdImageFile</b> (class) [<a href='#PIL.GdImageFile.GdImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for the GD uncompressed format. Note that this format
+is not supported by the standard <b>Image.open</b> function. To use
+this plugin, you have to import the <b>GdImageFile</b> module and
+use the <b>GdImageFile.open</b> function.
+</p></dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.GifImagePlugin.html b/Imaging/Docs/pythondoc-PIL.GifImagePlugin.html
new file mode 100644
index 0000000..06a0401
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.GifImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.GifImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.GifImagePlugin Module</h1>
+<dl>
+<dt><b>GifImageFile</b> (class) [<a href='#PIL.GifImagePlugin.GifImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for GIF images.</p>
+<p>For more information about this class, see <a href='#PIL.GifImagePlugin.GifImageFile-class'><i>The GifImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.GifImagePlugin.GifImageFile-class' name='PIL.GifImagePlugin.GifImageFile-class'>The GifImageFile Class</a></h2>
+<dl>
+<dt><b>GifImageFile</b> (class) [<a href='#PIL.GifImagePlugin.GifImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.GimpGradientFile.html b/Imaging/Docs/pythondoc-PIL.GimpGradientFile.html
new file mode 100644
index 0000000..d9e3d32
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.GimpGradientFile.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.GimpGradientFile Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.GimpGradientFile Module</h1>
+<dl>
+<dt><b>GimpGradientFile(fp)</b> (class) [<a href='#PIL.GimpGradientFile.GimpGradientFile-class'>#</a>]</dt>
+<dd>
+<p>File handler for GIMP's gradient format.</p>
+<p>For more information about this class, see <a href='#PIL.GimpGradientFile.GimpGradientFile-class'><i>The GimpGradientFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.GimpGradientFile.GimpGradientFile-class' name='PIL.GimpGradientFile.GimpGradientFile-class'>The GimpGradientFile Class</a></h2>
+<dl>
+<dt><b>GimpGradientFile(fp)</b> (class) [<a href='#PIL.GimpGradientFile.GimpGradientFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.GimpPaletteFile.html b/Imaging/Docs/pythondoc-PIL.GimpPaletteFile.html
new file mode 100644
index 0000000..421fc9c
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.GimpPaletteFile.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.GimpPaletteFile Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.GimpPaletteFile Module</h1>
+<dl>
+<dt><b>GimpPaletteFile(fp)</b> (class) [<a href='#PIL.GimpPaletteFile.GimpPaletteFile-class'>#</a>]</dt>
+<dd>
+<p>File handler for GIMP's palette format.</p>
+<p>For more information about this class, see <a href='#PIL.GimpPaletteFile.GimpPaletteFile-class'><i>The GimpPaletteFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.GimpPaletteFile.GimpPaletteFile-class' name='PIL.GimpPaletteFile.GimpPaletteFile-class'>The GimpPaletteFile Class</a></h2>
+<dl>
+<dt><b>GimpPaletteFile(fp)</b> (class) [<a href='#PIL.GimpPaletteFile.GimpPaletteFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.GribStubImagePlugin.html b/Imaging/Docs/pythondoc-PIL.GribStubImagePlugin.html
new file mode 100644
index 0000000..735db2b
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.GribStubImagePlugin.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.GribStubImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.GribStubImagePlugin Module</h1>
+<dl>
+<dt><a id='PIL.GribStubImagePlugin.register_handler-function' name='PIL.GribStubImagePlugin.register_handler-function'><b>register_handler(handler)</b></a> [<a href='#PIL.GribStubImagePlugin.register_handler-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>handler</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.Hdf5StubImagePlugin.html b/Imaging/Docs/pythondoc-PIL.Hdf5StubImagePlugin.html
new file mode 100644
index 0000000..d03591a
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.Hdf5StubImagePlugin.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.Hdf5StubImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.Hdf5StubImagePlugin Module</h1>
+<dl>
+<dt><a id='PIL.Hdf5StubImagePlugin.register_handler-function' name='PIL.Hdf5StubImagePlugin.register_handler-function'><b>register_handler(handler)</b></a> [<a href='#PIL.Hdf5StubImagePlugin.register_handler-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>handler</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.IcnsImagePlugin.html b/Imaging/Docs/pythondoc-PIL.IcnsImagePlugin.html
new file mode 100644
index 0000000..4a05314
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.IcnsImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.IcnsImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.IcnsImagePlugin Module</h1>
+<dl>
+<dt><b>IcnsImageFile</b> (class) [<a href='#PIL.IcnsImagePlugin.IcnsImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for Mac OS icons.</p>
+<p>For more information about this class, see <a href='#PIL.IcnsImagePlugin.IcnsImageFile-class'><i>The IcnsImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.IcnsImagePlugin.IcnsImageFile-class' name='PIL.IcnsImagePlugin.IcnsImageFile-class'>The IcnsImageFile Class</a></h2>
+<dl>
+<dt><b>IcnsImageFile</b> (class) [<a href='#PIL.IcnsImagePlugin.IcnsImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.IcoImagePlugin.html b/Imaging/Docs/pythondoc-PIL.IcoImagePlugin.html
new file mode 100644
index 0000000..5e2b923
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.IcoImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.IcoImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.IcoImagePlugin Module</h1>
+<dl>
+<dt><b>IcoImageFile</b> (class) [<a href='#PIL.IcoImagePlugin.IcoImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for Windows Icon files.</p>
+<p>For more information about this class, see <a href='#PIL.IcoImagePlugin.IcoImageFile-class'><i>The IcoImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.IcoImagePlugin.IcoImageFile-class' name='PIL.IcoImagePlugin.IcoImageFile-class'>The IcoImageFile Class</a></h2>
+<dl>
+<dt><b>IcoImageFile</b> (class) [<a href='#PIL.IcoImagePlugin.IcoImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImImagePlugin.html b/Imaging/Docs/pythondoc-PIL.ImImagePlugin.html
new file mode 100644
index 0000000..918f745
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImImagePlugin Module</h1>
+<dl>
+<dt><b>ImImageFile</b> (class) [<a href='#PIL.ImImagePlugin.ImImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for the IFUNC IM file format.</p>
+<p>For more information about this class, see <a href='#PIL.ImImagePlugin.ImImageFile-class'><i>The ImImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.ImImagePlugin.ImImageFile-class' name='PIL.ImImagePlugin.ImImageFile-class'>The ImImageFile Class</a></h2>
+<dl>
+<dt><b>ImImageFile</b> (class) [<a href='#PIL.ImImagePlugin.ImImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.Image.html b/Imaging/Docs/pythondoc-PIL.Image.html
new file mode 100644
index 0000000..e1a49c0
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.Image.html
@@ -0,0 +1,931 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.Image Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.Image Module</h1>
+<dl>
+<dt><a id='PIL.Image.blend-function' name='PIL.Image.blend-function'><b>blend(im1, im2, alpha)</b></a> [<a href='#PIL.Image.blend-function'>#</a>]</dt>
+<dd>
+<p>Creates a new image by interpolating between two input images, using
+a constant alpha.
+
+<pre>
+ out = image1 * (1.0 - alpha) + image2 * alpha
+</pre>
+
+</p><dl>
+<dt><i>im1</i></dt>
+<dd>
+</dd>
+<dt><i>im2</i></dt>
+<dd>
+</dd>
+<dt><i>alpha</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.composite-function' name='PIL.Image.composite-function'><b>composite(image1, image2, mask)</b></a> [<a href='#PIL.Image.composite-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>image1</i></dt>
+<dd>
+</dd>
+<dt><i>image2</i></dt>
+<dd>
+</dd>
+<dt><i>mask</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.eval-function' name='PIL.Image.eval-function'><b>eval(image, function)</b></a> [<a href='#PIL.Image.eval-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt><i>function</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.frombuffer-function' name='PIL.Image.frombuffer-function'><b>frombuffer(mode, size, data, decoder_name=&quot;raw&quot;, *args)</b></a> [<a href='#PIL.Image.frombuffer-function'>#</a>]</dt>
+<dd>
+<p>(New in 1.1.4) Creates an image memory from pixel data in a string
+or byte buffer.
+</p><p>
+This function is similar to <a class="link" href="#PIL.Image.fromstring-function"><b>fromstring</b></a>, but uses data in
+the byte buffer, where possible. This means that changes to the
+original buffer object are reflected in this image). Not all modes
+can share memory; support modes include "L", "RGBX", "RGBA", and
+"CMYK". For other modes, this function behaves like a corresponding
+call to the <b>fromstring</b> function.
+</p><p>
+Note that this function decodes pixel data only, not entire images.
+If you have an entire image file in a string, wrap it in a
+<b>StringIO</b> object, and use <a class="link" href="#PIL.Image.open-function"><b>open</b></a> to load it.
+
+</p><dl>
+<dt><i>mode</i></dt>
+<dd>
+</dd>
+<dt><i>size</i></dt>
+<dd>
+</dd>
+<dt><i>data</i></dt>
+<dd>
+</dd>
+<dt><i>decoder_name</i></dt>
+<dd>
+</dd>
+<dt><i>*args</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.fromstring-function' name='PIL.Image.fromstring-function'><b>fromstring(mode, size, data, decoder_name=&quot;raw&quot;, *args)</b></a> [<a href='#PIL.Image.fromstring-function'>#</a>]</dt>
+<dd>
+<p>Creates an image memory from pixel data in a string.
+</p><p>
+In its simplest form, this function takes three arguments
+(mode, size, and unpacked pixel data).
+</p><p>
+You can also use any pixel decoder supported by PIL. For more
+information on available decoders, see the section <a href="pil-decoder.htm"><i>Writing Your Own File Decoder</i></a>.
+</p><p>
+Note that this function decodes pixel data only, not entire images.
+If you have an entire image in a string, wrap it in a
+<b>StringIO</b> object, and use <a class="link" href="#PIL.Image.open-function"><b>open</b></a> to load it.
+
+</p><dl>
+<dt><i>mode</i></dt>
+<dd>
+</dd>
+<dt><i>size</i></dt>
+<dd>
+</dd>
+<dt><i>data</i></dt>
+<dd>
+</dd>
+<dt><i>decoder_name</i></dt>
+<dd>
+</dd>
+<dt><i>*args</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.getmodebandnames-function' name='PIL.Image.getmodebandnames-function'><b>getmodebandnames(mode)</b></a> [<a href='#PIL.Image.getmodebandnames-function'>#</a>]</dt>
+<dd>
+<p>Gets a list of individual band names. Given a mode, this function
+returns a tuple containing the names of individual bands (use
+<a class="link" href="#PIL.Image.getmodetype-function"><b>getmodetype</b></a> to get the mode used to store each individual
+band.
+
+</p><dl>
+<dt><i>mode</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+<dt>Raises <b>KeyError</b>:</dt><dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.getmodebands-function' name='PIL.Image.getmodebands-function'><b>getmodebands(mode)</b></a> [<a href='#PIL.Image.getmodebands-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>mode</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+<dt>Raises <b>KeyError</b>:</dt><dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.getmodebase-function' name='PIL.Image.getmodebase-function'><b>getmodebase(mode)</b></a> [<a href='#PIL.Image.getmodebase-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>mode</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+<dt>Raises <b>KeyError</b>:</dt><dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.getmodetype-function' name='PIL.Image.getmodetype-function'><b>getmodetype(mode)</b></a> [<a href='#PIL.Image.getmodetype-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>mode</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+<dt>Raises <b>KeyError</b>:</dt><dd>
+</dd>
+</dl><br />
+</dd>
+<dt><b>Image()</b> (class) [<a href='#PIL.Image.Image-class'>#</a>]</dt>
+<dd>
+<p>This class represents an image object.</p>
+<p>For more information about this class, see <a href='#PIL.Image.Image-class'><i>The Image Class</i></a>.</p>
+</dd>
+<dt><a id='PIL.Image.init-function' name='PIL.Image.init-function'><b>init()</b></a> [<a href='#PIL.Image.init-function'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.Image.isDirectory-function' name='PIL.Image.isDirectory-function'><b>isDirectory(f)</b></a> [<a href='#PIL.Image.isDirectory-function'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.Image.isImageType-function' name='PIL.Image.isImageType-function'><b>isImageType(t)</b></a> [<a href='#PIL.Image.isImageType-function'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.Image.isStringType-function' name='PIL.Image.isStringType-function'><b>isStringType(t)</b></a> [<a href='#PIL.Image.isStringType-function'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.Image.isTupleType-function' name='PIL.Image.isTupleType-function'><b>isTupleType(t)</b></a> [<a href='#PIL.Image.isTupleType-function'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.Image.merge-function' name='PIL.Image.merge-function'><b>merge(mode, bands)</b></a> [<a href='#PIL.Image.merge-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>mode</i></dt>
+<dd>
+</dd>
+<dt><i>bands</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.new-function' name='PIL.Image.new-function'><b>new(mode, size, color=0)</b></a> [<a href='#PIL.Image.new-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>mode</i></dt>
+<dd>
+</dd>
+<dt><i>size</i></dt>
+<dd>
+</dd>
+<dt><i>color</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.open-function' name='PIL.Image.open-function'><b>open(file, mode=&quot;r&quot;)</b></a> [<a href='#PIL.Image.open-function'>#</a>]</dt>
+<dd>
+<p>Opens and identifies the given image file.
+</p><p>
+This is a lazy operation; this function identifies the file, but the
+actual image data is not read from the file until you try to process
+the data (or call the <a class="link" href="#PIL.Image.Image.load-method"><b>load</b></a> method).
+
+</p><dl>
+<dt><i>file</i></dt>
+<dd>
+A filename (string) or a file object. The file object
+ must implement <b>read</b>, <b>seek</b>, and <b>tell</b> methods,
+ and be opened in binary mode.
+</dd>
+<dt><i>mode</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+<dt>Raises <b>IOError</b>:</dt><dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.preinit-function' name='PIL.Image.preinit-function'><b>preinit()</b></a> [<a href='#PIL.Image.preinit-function'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.Image.register_extension-function' name='PIL.Image.register_extension-function'><b>register_extension(id, extension)</b></a> [<a href='#PIL.Image.register_extension-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>id</i></dt>
+<dd>
+</dd>
+<dt><i>extension</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.register_mime-function' name='PIL.Image.register_mime-function'><b>register_mime(id, mimetype)</b></a> [<a href='#PIL.Image.register_mime-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>id</i></dt>
+<dd>
+</dd>
+<dt><i>mimetype</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.register_open-function' name='PIL.Image.register_open-function'><b>register_open(id, factory, accept=None)</b></a> [<a href='#PIL.Image.register_open-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>id</i></dt>
+<dd>
+</dd>
+<dt><i>factory</i></dt>
+<dd>
+</dd>
+<dt><i>accept</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.register_save-function' name='PIL.Image.register_save-function'><b>register_save(id, driver)</b></a> [<a href='#PIL.Image.register_save-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>id</i></dt>
+<dd>
+</dd>
+<dt><i>driver</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+<h2><a id='PIL.Image.Image-class' name='PIL.Image.Image-class'>The Image Class</a></h2>
+<dl>
+<dt><b>Image()</b> (class) [<a href='#PIL.Image.Image-class'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.Image.Image.convert-method' name='PIL.Image.Image.convert-method'><b>convert(mode, matrix=None)</b></a> [<a href='#PIL.Image.Image.convert-method'>#</a>]</dt>
+<dd>
+<p>Returns a converted copy of this image. For the "P" mode, this
+method translates pixels through the palette. If mode is
+omitted, a mode is chosen so that all information in the image
+and the palette can be represented without a palette.
+</p><p>
+The current version supports all possible conversions between
+"L", "RGB" and "CMYK."
+</p><p>
+When translating a colour image to black and white (mode "L"),
+the library uses the ITU-R 601-2 luma transform:
+</p><p>
+<b>L = R * 299/1000 + G * 587/1000 + B * 114/1000</b>
+</p><p>
+When translating a greyscale image into a bilevel image (mode
+"1"), all non-zero values are set to 255 (white). To use other
+thresholds, use the <a class="link" href="#PIL.Image.Image.point-method"><b>point</b></a> method.
+
+</p><dl>
+<dt><i>mode</i></dt>
+<dd>
+</dd>
+<dt><i>matrix</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.copy-method' name='PIL.Image.Image.copy-method'><b>copy()</b></a> [<a href='#PIL.Image.Image.copy-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.crop-method' name='PIL.Image.Image.crop-method'><b>crop(box=None)</b></a> [<a href='#PIL.Image.Image.crop-method'>#</a>]</dt>
+<dd>
+<p>Returns a rectangular region from this image. The box is a
+4-tuple defining the left, upper, right, and lower pixel
+coordinate.
+</p><p>
+This is a lazy operation. Changes to the source image may or
+may not be reflected in the cropped image. To break the
+connection, call the <a class="link" href="#PIL.Image.Image.load-method"><b>load</b></a> method on the cropped
+copy.
+
+</p><dl>
+<dt><i>The</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.draft-method' name='PIL.Image.Image.draft-method'><b>draft(mode, size)</b></a> [<a href='#PIL.Image.Image.draft-method'>#</a>]</dt>
+<dd>
+<p>Configures the image file loader so it returns a version of the
+image that as closely as possible matches the given mode and
+size. For example, you can use this method to convert a colour
+JPEG to greyscale while loading it, or to extract a 128x192
+version from a PCD file.
+</p><p>
+Note that this method modifies the Image object in place. If
+the image has already been loaded, this method has no effect.
+
+</p><dl>
+<dt><i>mode</i></dt>
+<dd>
+</dd>
+<dt><i>size</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.filter-method' name='PIL.Image.Image.filter-method'><b>filter(filter)</b></a> [<a href='#PIL.Image.Image.filter-method'>#</a>]</dt>
+<dd>
+<p>Filters this image using the given filter. For a list of
+available filters, see the <b>ImageFilter</b> module.
+
+</p><dl>
+<dt><i>filter</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.fromstring-method' name='PIL.Image.Image.fromstring-method'><b>fromstring(data, decoder_name=&quot;raw&quot;, *args)</b></a> [<a href='#PIL.Image.Image.fromstring-method'>#</a>]</dt>
+<dd>
+<p>Loads this image with pixel data from a string.
+</p><p>
+This method is similar to the <a class="link" href="#PIL.Image.fromstring-function"><b>fromstring</b></a> function, but
+loads data into this image instead of creating a new image
+object.
+</p></dd>
+<dt><a id='PIL.Image.Image.getbands-method' name='PIL.Image.Image.getbands-method'><b>getbands()</b></a> [<a href='#PIL.Image.Image.getbands-method'>#</a>]</dt>
+<dd>
+<p>Returns a tuple containing the name of each band in this image.
+For example, <b>getbands</b> on an RGB image returns ("R", "G", "B").
+
+</p><dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.getbbox-method' name='PIL.Image.Image.getbbox-method'><b>getbbox()</b></a> [<a href='#PIL.Image.Image.getbbox-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.getcolors-method' name='PIL.Image.Image.getcolors-method'><b>getcolors(maxcolors=256)</b></a> [<a href='#PIL.Image.Image.getcolors-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>maxcolors</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.getdata-method' name='PIL.Image.Image.getdata-method'><b>getdata(band=None)</b></a> [<a href='#PIL.Image.Image.getdata-method'>#</a>]</dt>
+<dd>
+<p>Returns the contents of this image as a sequence object
+containing pixel values. The sequence object is flattened, so
+that values for line one follow directly after the values of
+line zero, and so on.
+</p><p>
+Note that the sequence object returned by this method is an
+internal PIL data type, which only supports certain sequence
+operations. To convert it to an ordinary sequence (e.g. for
+printing), use <b>list(im.getdata())</b>.
+
+</p><dl>
+<dt><i>band</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.getextrema-method' name='PIL.Image.Image.getextrema-method'><b>getextrema()</b></a> [<a href='#PIL.Image.Image.getextrema-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.getim-method' name='PIL.Image.Image.getim-method'><b>getim()</b></a> [<a href='#PIL.Image.Image.getim-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.getpalette-method' name='PIL.Image.Image.getpalette-method'><b>getpalette()</b></a> [<a href='#PIL.Image.Image.getpalette-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.getpixel-method' name='PIL.Image.Image.getpixel-method'><b>getpixel(xy)</b></a> [<a href='#PIL.Image.Image.getpixel-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>xy</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.getprojection-method' name='PIL.Image.Image.getprojection-method'><b>getprojection()</b></a> [<a href='#PIL.Image.Image.getprojection-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.histogram-method' name='PIL.Image.Image.histogram-method'><b>histogram(mask=None)</b></a> [<a href='#PIL.Image.Image.histogram-method'>#</a>]</dt>
+<dd>
+<p>Returns a histogram for the image. The histogram is returned as
+a list of pixel counts, one for each pixel value in the source
+image. If the image has more than one band, the histograms for
+all bands are concatenated (for example, the histogram for an
+"RGB" image contains 768 values).
+</p><p>
+A bilevel image (mode "1") is treated as a greyscale ("L") image
+by this method.
+</p><p>
+If a mask is provided, the method returns a histogram for those
+parts of the image where the mask image is non-zero. The mask
+image must have the same size as the image, and be either a
+bi-level image (mode "1") or a greyscale image ("L").
+
+</p><dl>
+<dt><i>mask</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.load-method' name='PIL.Image.Image.load-method'><b>load()</b></a> [<a href='#PIL.Image.Image.load-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.offset-method' name='PIL.Image.Image.offset-method'><b>offset(xoffset, yoffset=None)</b></a> [<a href='#PIL.Image.Image.offset-method'>#</a>]</dt>
+<dd>
+<p>(Deprecated) Returns a copy of the image where the data has been
+offset by the given distances. Data wraps around the edges. If
+yoffset is omitted, it is assumed to be equal to xoffset.
+</p><p>
+This method is deprecated. New code should use the <b>offset</b>
+function in the <b>ImageChops</b> module.
+
+</p><dl>
+<dt><i>xoffset</i></dt>
+<dd>
+</dd>
+<dt><i>yoffset</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.paste-method' name='PIL.Image.Image.paste-method'><b>paste(im, box=None, mask=None)</b></a> [<a href='#PIL.Image.Image.paste-method'>#</a>]</dt>
+<dd>
+<p>Pastes another image into this image. The box argument is either
+a 2-tuple giving the upper left corner, a 4-tuple defining the
+left, upper, right, and lower pixel coordinate, or None (same as
+(0, 0)). If a 4-tuple is given, the size of the pasted image
+must match the size of the region.
+</p><p>
+If the modes don't match, the pasted image is converted to the
+mode of this image (see the <a class="link" href="#PIL.Image.Image.convert-method"><b>convert</b></a> method for
+details).
+</p><p>
+Instead of an image, the source can be a integer or tuple
+containing pixel values. The method then fills the region
+with the given colour. When creating RGB images, you can
+also use colour strings as supported by the ImageColor module.
+</p><p>
+If a mask is given, this method updates only the regions
+indicated by the mask. You can use either "1", "L" or "RGBA"
+images (in the latter case, the alpha band is used as mask).
+Where the mask is 255, the given image is copied as is. Where
+the mask is 0, the current value is preserved. Intermediate
+values can be used for transparency effects.
+</p><p>
+Note that if you paste an "RGBA" image, the alpha band is
+ignored. You can work around this by using the same image as
+both source image and mask.
+
+</p><dl>
+<dt><i>im</i></dt>
+<dd>
+</dd>
+<dt><i>box</i></dt>
+<dd>
+<p>An optional 4-tuple giving the region to paste into.
+ If a 2-tuple is used instead, it's treated as the upper left
+ corner. If omitted or None, the source is pasted into the
+ upper left corner.
+ </p><p>
+ If an image is given as the second argument and there is no
+ third, the box defaults to (0, 0), and the second argument
+ is interpreted as a mask image.
+</p></dd>
+<dt><i>mask</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.point-method' name='PIL.Image.Image.point-method'><b>point(lut, mode=None)</b></a> [<a href='#PIL.Image.Image.point-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>lut</i></dt>
+<dd>
+</dd>
+<dt><i>mode</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.putalpha-method' name='PIL.Image.Image.putalpha-method'><b>putalpha(alpha)</b></a> [<a href='#PIL.Image.Image.putalpha-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>im</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.putdata-method' name='PIL.Image.Image.putdata-method'><b>putdata(data, scale=1.0, offset=0.0)</b></a> [<a href='#PIL.Image.Image.putdata-method'>#</a>]</dt>
+<dd>
+<p>Copies pixel data to this image. This method copies data from a
+sequence object into the image, starting at the upper left
+corner (0, 0), and continuing until either the image or the
+sequence ends. The scale and offset values are used to adjust
+the sequence values: <b>pixel = value*scale + offset</b>.
+
+</p><dl>
+<dt><i>data</i></dt>
+<dd>
+</dd>
+<dt><i>scale</i></dt>
+<dd>
+</dd>
+<dt><i>offset</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.putpalette-method' name='PIL.Image.Image.putpalette-method'><b>putpalette(data)</b></a> [<a href='#PIL.Image.Image.putpalette-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>data</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.putpixel-method' name='PIL.Image.Image.putpixel-method'><b>putpixel(xy, value)</b></a> [<a href='#PIL.Image.Image.putpixel-method'>#</a>]</dt>
+<dd>
+<p>Modifies the pixel at the given position. The colour is given as
+a single numerical value for single-band images, and a tuple for
+multi-band images.
+</p><p>
+Note that this method is relatively slow. For more extensive
+changes, use <a class="link" href="#PIL.Image.Image.paste-method"><b>paste</b></a> or the <b>ImageDraw</b> module
+instead.
+
+</p><dl>
+<dt><i>xy</i></dt>
+<dd>
+</dd>
+<dt><i>value</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.resize-method' name='PIL.Image.Image.resize-method'><b>resize(size, filter=NEAREST)</b></a> [<a href='#PIL.Image.Image.resize-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>size</i></dt>
+<dd>
+</dd>
+<dt><i>filter</i></dt>
+<dd>
+An optional resampling filter. This can be
+ one of <b>NEAREST</b> (use nearest neighbour), <b>BILINEAR</b>
+ (linear interpolation in a 2x2 environment), <b>BICUBIC</b>
+ (cubic spline interpolation in a 4x4 environment), or
+ <b>ANTIALIAS</b> (a high-quality downsampling filter).
+ If omitted, or if the image has mode "1" or "P", it is
+ set <b>NEAREST</b>.
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.rotate-method' name='PIL.Image.Image.rotate-method'><b>rotate(angle, filter=NEAREST)</b></a> [<a href='#PIL.Image.Image.rotate-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>angle</i></dt>
+<dd>
+</dd>
+<dt><i>filter</i></dt>
+<dd>
+An optional resampling filter. This can be
+ one of <b>NEAREST</b> (use nearest neighbour), <b>BILINEAR</b>
+ (linear interpolation in a 2x2 environment), or <b>BICUBIC</b>
+ (cubic spline interpolation in a 4x4 environment).
+ If omitted, or if the image has mode "1" or "P", it is
+ set <b>NEAREST</b>.
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.save-method' name='PIL.Image.Image.save-method'><b>save(file, format=None, **options)</b></a> [<a href='#PIL.Image.Image.save-method'>#</a>]</dt>
+<dd>
+<p>Saves this image under the given filename. If no format is
+specified, the format to use is determined from the filename
+extension, if possible.
+</p><p>
+Keyword options can be used to provide additional instructions
+to the writer. If a writer doesn't recognise an option, it is
+silently ignored. The available options are described later in
+this handbook.
+</p><p>
+You can use a file object instead of a filename. In this case,
+you must always specify the format. The file object must
+implement the <b>seek</b>, <b>tell</b>, and <b>write</b>
+methods, and be opened in binary mode.
+
+</p><dl>
+<dt><i>file</i></dt>
+<dd>
+</dd>
+<dt><i>format</i></dt>
+<dd>
+</dd>
+<dt><i>**options</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+<dt>Raises <b>KeyError</b>:</dt><dd>
+</dd>
+<dt>Raises <b>IOError</b>:</dt><dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.seek-method' name='PIL.Image.Image.seek-method'><b>seek(frame)</b></a> [<a href='#PIL.Image.Image.seek-method'>#</a>]</dt>
+<dd>
+<p>Seeks to the given frame in this sequence file. If you seek
+beyond the end of the sequence, the method raises an
+<b>EOFError</b> exception. When a sequence file is opened, the
+library automatically seeks to frame 0.
+</p><p>
+Note that in the current version of the library, most sequence
+formats only allows you to seek to the next frame.
+
+</p><dl>
+<dt><i>frame</i></dt>
+<dd>
+</dd>
+<dt>Raises <b>EOFError</b>:</dt><dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.show-method' name='PIL.Image.Image.show-method'><b>show(title=None)</b></a> [<a href='#PIL.Image.Image.show-method'>#</a>]</dt>
+<dd>
+<p>Displays this image. This method is mainly intended for
+debugging purposes.
+</p><p>
+On Unix platforms, this method saves the image to a temporary
+PPM file, and calls the <b>xv</b> utility.
+</p><p>
+On Windows, it saves the image to a temporary BMP file, and uses
+the standard BMP display utility to show it (usually Paint).
+
+</p><dl>
+<dt><i>title</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.split-method' name='PIL.Image.Image.split-method'><b>split()</b></a> [<a href='#PIL.Image.Image.split-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.tell-method' name='PIL.Image.Image.tell-method'><b>tell()</b></a> [<a href='#PIL.Image.Image.tell-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.thumbnail-method' name='PIL.Image.Image.thumbnail-method'><b>thumbnail(size, resample=NEAREST)</b></a> [<a href='#PIL.Image.Image.thumbnail-method'>#</a>]</dt>
+<dd>
+<p>Make this image into a thumbnail. This method modifies the
+image to contain a thumbnail version of itself, no larger than
+the given size. This method calculates an appropriate thumbnail
+size to preserve the aspect of the image, calls the <a class="link" href="#PIL.Image.Image.draft-method"><b>draft</b></a> method to configure the file reader (where
+applicable), and finally resizes the image.
+</p><p>
+Note that the bilinear and bicubic filters in the current
+version of PIL are not well-suited for thumbnail generation.
+You should use <b>ANTIALIAS</b> unless speed is much more
+important than quality.
+</p><p>
+Also note that this function modifies the Image object in place.
+If you need to use the full resolution image as well, apply this
+method to a <a class="link" href="#PIL.Image.Image.copy-method"><b>copy</b></a> of the original image.
+
+</p><dl>
+<dt><i>size</i></dt>
+<dd>
+</dd>
+<dt><i>resample</i></dt>
+<dd>
+Optional resampling filter. This can be one
+ of <b>NEAREST</b>, <b>BILINEAR</b>, <b>BICUBIC</b>, or
+ <b>ANTIALIAS</b> (best quality). If omitted, it defaults
+ to <b>NEAREST</b> (this will be changed to ANTIALIAS in a
+ future version).
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.tobitmap-method' name='PIL.Image.Image.tobitmap-method'><b>tobitmap(name=&quot;image&quot;)</b></a> [<a href='#PIL.Image.Image.tobitmap-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>name</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+<dt>Raises <b>ValueError</b>:</dt><dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.tostring-method' name='PIL.Image.Image.tostring-method'><b>tostring(encoder_name=&quot;raw&quot;, *args)</b></a> [<a href='#PIL.Image.Image.tostring-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>encoder_name</i></dt>
+<dd>
+</dd>
+<dt><i>*args</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.transform-method' name='PIL.Image.Image.transform-method'><b>transform(size, method, data, resample=NEAREST)</b></a> [<a href='#PIL.Image.Image.transform-method'>#</a>]</dt>
+<dd>
+<p>Transforms this image. This method creates a new image with the
+given size, and the same mode as the original, and copies data
+to the new image using the given transform.
+</p><p>
+</p><dl>
+<dt><i>size</i></dt>
+<dd>
+</dd>
+<dt><i>method</i></dt>
+<dd>
+The transformation method. This is one of
+ <b>EXTENT</b> (cut out a rectangular subregion), <b>AFFINE</b>
+ (affine transform), <b>PERSPECTIVE</b> (perspective
+ transform), <b>QUAD</b> (map a quadrilateral to a
+ rectangle), or <b>MESH</b> (map a number of source quadrilaterals
+ in one operation).
+</dd>
+<dt><i>data</i></dt>
+<dd>
+</dd>
+<dt><i>resample</i></dt>
+<dd>
+Optional resampling filter. It can be one of
+ <b>NEAREST</b> (use nearest neighbour), <b>BILINEAR</b>
+ (linear interpolation in a 2x2 environment), or
+ <b>BICUBIC</b> (cubic spline interpolation in a 4x4
+ environment). If omitted, or if the image has mode
+ "1" or "P", it is set to <b>NEAREST</b>.
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.transpose-method' name='PIL.Image.Image.transpose-method'><b>transpose(method)</b></a> [<a href='#PIL.Image.Image.transpose-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>method</i></dt>
+<dd>
+One of <b>FLIP_LEFT_RIGHT</b>, <b>FLIP_TOP_BOTTOM</b>,
+<b>ROTATE_90</b>, <b>ROTATE_180</b>, or <b>ROTATE_270</b>.
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.Image.Image.verify-method' name='PIL.Image.Image.verify-method'><b>verify()</b></a> [<a href='#PIL.Image.Image.verify-method'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImageChops.html b/Imaging/Docs/pythondoc-PIL.ImageChops.html
new file mode 100644
index 0000000..2e665b5
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImageChops.html
@@ -0,0 +1,282 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImageChops Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImageChops Module</h1>
+<p>The <b>ImageChops</b> module contains a number of arithmetical image
+operations, called <i>channel operations</i> ("chops"). These can be
+used for various purposes, including special effects, image
+compositions, algorithmic painting, and more.
+</p><p>
+At this time, channel operations are only implemented for 8-bit
+images (e.g. "L" and "RGB").
+</p><p>
+Most channel operations take one or two image arguments and returns
+a new image. Unless otherwise noted, the result of a channel
+operation is always clipped to the range 0 to MAX (which is 255 for
+all modes supported by the operations in this module).
+</p><h2>Module Contents</h2>
+<dl>
+<dt><a id='PIL.ImageChops.add-function' name='PIL.ImageChops.add-function'><b>add(image1, image2, scale=1.0, offset=0)</b></a> [<a href='#PIL.ImageChops.add-function'>#</a>]</dt>
+<dd>
+<p>Add images
+((image1 + image2) / scale + offset).
+</p><p>
+Adds two images, dividing the result by scale and adding the
+offset. If omitted, scale defaults to 1.0, and offset to 0.0.
+
+</p><dl>
+<dt><i>image1</i></dt>
+<dd>
+</dd>
+<dt><i>image1</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageChops.add_modulo-function' name='PIL.ImageChops.add_modulo-function'><b>add_modulo(image1, image2)</b></a> [<a href='#PIL.ImageChops.add_modulo-function'>#</a>]</dt>
+<dd>
+<p>Add images without clipping
+((image1 + image2) % MAX).
+</p><p>
+Adds two images, without clipping the result.
+
+</p><dl>
+<dt><i>image1</i></dt>
+<dd>
+</dd>
+<dt><i>image1</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageChops.blend-function' name='PIL.ImageChops.blend-function'><b>blend(image1, image2, alpha)</b></a> [<a href='#PIL.ImageChops.blend-function'>#</a>]</dt>
+<dd>
+<p>Blend images using constant transparency weight.
+</p><p>
+Same as the <b>blend</b> function in the <b>Image</b> module.
+</p></dd>
+<dt><a id='PIL.ImageChops.composite-function' name='PIL.ImageChops.composite-function'><b>composite(image1, image2, mask)</b></a> [<a href='#PIL.ImageChops.composite-function'>#</a>]</dt>
+<dd>
+<p>Create composite using transparency mask.
+</p><p>
+Same as the <b>composite</b> function in the <b>Image</b> module.
+</p></dd>
+<dt><a id='PIL.ImageChops.constant-function' name='PIL.ImageChops.constant-function'><b>constant(image, value)</b></a> [<a href='#PIL.ImageChops.constant-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt><i>value</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageChops.darker-function' name='PIL.ImageChops.darker-function'><b>darker(image1, image2)</b></a> [<a href='#PIL.ImageChops.darker-function'>#</a>]</dt>
+<dd>
+<p>Compare images, and return darker pixel value
+(min(image1, image2)).
+</p><p>
+Compares the two images, pixel by pixel, and returns a new image
+containing the darker values.
+
+</p><dl>
+<dt><i>image1</i></dt>
+<dd>
+</dd>
+<dt><i>image1</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageChops.difference-function' name='PIL.ImageChops.difference-function'><b>difference(image1, image2)</b></a> [<a href='#PIL.ImageChops.difference-function'>#</a>]</dt>
+<dd>
+<p>Calculate absolute difference
+(abs(image1 - image2)).
+</p><p>
+Returns the absolute value of the difference between the two images.
+
+</p><dl>
+<dt><i>image1</i></dt>
+<dd>
+</dd>
+<dt><i>image1</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageChops.duplicate-function' name='PIL.ImageChops.duplicate-function'><b>duplicate(image)</b></a> [<a href='#PIL.ImageChops.duplicate-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageChops.invert-function' name='PIL.ImageChops.invert-function'><b>invert(image)</b></a> [<a href='#PIL.ImageChops.invert-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageChops.lighter-function' name='PIL.ImageChops.lighter-function'><b>lighter(image1, image2)</b></a> [<a href='#PIL.ImageChops.lighter-function'>#</a>]</dt>
+<dd>
+<p>Compare images, and return lighter pixel value
+(max(image1, image2)).
+</p><p>
+Compares the two images, pixel by pixel, and returns a new image
+containing the lighter values.
+
+</p><dl>
+<dt><i>image1</i></dt>
+<dd>
+</dd>
+<dt><i>image1</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageChops.logical_and-function' name='PIL.ImageChops.logical_and-function'><b>logical_and(image1, image2)</b></a> [<a href='#PIL.ImageChops.logical_and-function'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageChops.logical_or-function' name='PIL.ImageChops.logical_or-function'><b>logical_or(image1, image2)</b></a> [<a href='#PIL.ImageChops.logical_or-function'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageChops.logical_xor-function' name='PIL.ImageChops.logical_xor-function'><b>logical_xor(image1, image2)</b></a> [<a href='#PIL.ImageChops.logical_xor-function'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageChops.multiply-function' name='PIL.ImageChops.multiply-function'><b>multiply(image1, image2)</b></a> [<a href='#PIL.ImageChops.multiply-function'>#</a>]</dt>
+<dd>
+<p>Superimpose positive images
+(image1 * image2 / MAX).
+</p><p>
+Superimposes two images on top of each other. If you multiply an
+image with a solid black image, the result is black. If you multiply
+with a solid white image, the image is unaffected.
+
+</p><dl>
+<dt><i>image1</i></dt>
+<dd>
+</dd>
+<dt><i>image1</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageChops.offset-function' name='PIL.ImageChops.offset-function'><b>offset(image, xoffset, yoffset=None)</b></a> [<a href='#PIL.ImageChops.offset-function'>#</a>]</dt>
+<dd>
+<p>Offset image data.
+</p><p>
+Returns a copy of the image where data has been offset by the given
+distances. Data wraps around the edges. If yoffset is omitted, it
+is assumed to be equal to xoffset.
+
+</p><dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt><i>xoffset</i></dt>
+<dd>
+</dd>
+<dt><i>yoffset</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageChops.screen-function' name='PIL.ImageChops.screen-function'><b>screen(image1, image2)</b></a> [<a href='#PIL.ImageChops.screen-function'>#</a>]</dt>
+<dd>
+<p>Superimpose negative images
+(MAX - ((MAX - image1) * (MAX - image2) / MAX)).
+</p><p>
+Superimposes two inverted images on top of each other.
+
+</p><dl>
+<dt><i>image1</i></dt>
+<dd>
+</dd>
+<dt><i>image1</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageChops.subtract-function' name='PIL.ImageChops.subtract-function'><b>subtract(image1, image2, scale=1.0, offset=0)</b></a> [<a href='#PIL.ImageChops.subtract-function'>#</a>]</dt>
+<dd>
+<p>Subtract images
+((image1 - image2) / scale + offset).
+</p><p>
+Subtracts two images, dividing the result by scale and adding the
+offset. If omitted, scale defaults to 1.0, and offset to 0.0.
+
+</p><dl>
+<dt><i>image1</i></dt>
+<dd>
+</dd>
+<dt><i>image1</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageChops.subtract_modulo-function' name='PIL.ImageChops.subtract_modulo-function'><b>subtract_modulo(image1, image2)</b></a> [<a href='#PIL.ImageChops.subtract_modulo-function'>#</a>]</dt>
+<dd>
+<p>Subtract images without clipping
+((image1 - image2) % MAX).
+</p><p>
+Subtracts two images, without clipping the result.
+
+</p><dl>
+<dt><i>image1</i></dt>
+<dd>
+</dd>
+<dt><i>image1</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImageColor.html b/Imaging/Docs/pythondoc-PIL.ImageColor.html
new file mode 100644
index 0000000..b409ccf
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImageColor.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImageColor Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImageColor Module</h1>
+<dl>
+<dt><a id='PIL.ImageColor.getrgb-function' name='PIL.ImageColor.getrgb-function'><b>getrgb(color)</b></a> [<a href='#PIL.ImageColor.getrgb-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>color</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+<dt>Raises <b>ValueError</b>:</dt><dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImageDraw.html b/Imaging/Docs/pythondoc-PIL.ImageDraw.html
new file mode 100644
index 0000000..1e72665
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImageDraw.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImageDraw Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImageDraw Module</h1>
+<dl>
+<dt><a id='PIL.ImageDraw.Draw-function' name='PIL.ImageDraw.Draw-function'><b>Draw(im, mode=None)</b></a> [<a href='#PIL.ImageDraw.Draw-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>im</i></dt>
+<dd>
+</dd>
+<dt><i>mode</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageDraw.getdraw-function' name='PIL.ImageDraw.getdraw-function'><b>getdraw(im=None, hints=None)</b></a> [<a href='#PIL.ImageDraw.getdraw-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>im</i></dt>
+<dd>
+</dd>
+<dt><i>hints</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><b>ImageDraw(im, mode=None)</b> (class) [<a href='#PIL.ImageDraw.ImageDraw-class'>#</a>]</dt>
+<dd>
+<p>A simple 2D drawing interface for PIL images.</p>
+<p>For more information about this class, see <a href='#PIL.ImageDraw.ImageDraw-class'><i>The ImageDraw Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.ImageDraw.ImageDraw-class' name='PIL.ImageDraw.ImageDraw-class'>The ImageDraw Class</a></h2>
+<dl>
+<dt><b>ImageDraw(im, mode=None)</b> (class) [<a href='#PIL.ImageDraw.ImageDraw-class'>#</a>]</dt>
+<dd>
+<p>A simple 2D drawing interface for PIL images.
+</p><p>
+Application code should use the <b>Draw</b> factory, instead of
+directly.
+</p></dd>
+<dt><a id='PIL.ImageDraw.ImageDraw.__init__-method' name='PIL.ImageDraw.ImageDraw.__init__-method'><b>__init__(im, mode=None)</b></a> [<a href='#PIL.ImageDraw.ImageDraw.__init__-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>im</i></dt>
+<dd>
+</dd>
+<dt><i>mode</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageDraw.ImageDraw.arc-method' name='PIL.ImageDraw.ImageDraw.arc-method'><b>arc(xy, start, end, fill=None)</b></a> [<a href='#PIL.ImageDraw.ImageDraw.arc-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageDraw.ImageDraw.bitmap-method' name='PIL.ImageDraw.ImageDraw.bitmap-method'><b>bitmap(xy, bitmap, fill=None)</b></a> [<a href='#PIL.ImageDraw.ImageDraw.bitmap-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageDraw.ImageDraw.chord-method' name='PIL.ImageDraw.ImageDraw.chord-method'><b>chord(xy, start, end, fill=None, outline=None)</b></a> [<a href='#PIL.ImageDraw.ImageDraw.chord-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageDraw.ImageDraw.ellipse-method' name='PIL.ImageDraw.ImageDraw.ellipse-method'><b>ellipse(xy, fill=None, outline=None)</b></a> [<a href='#PIL.ImageDraw.ImageDraw.ellipse-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageDraw.ImageDraw.getfont-method' name='PIL.ImageDraw.ImageDraw.getfont-method'><b>getfont()</b></a> [<a href='#PIL.ImageDraw.ImageDraw.getfont-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageDraw.ImageDraw.line-method' name='PIL.ImageDraw.ImageDraw.line-method'><b>line(xy, fill=None, width=0)</b></a> [<a href='#PIL.ImageDraw.ImageDraw.line-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageDraw.ImageDraw.pieslice-method' name='PIL.ImageDraw.ImageDraw.pieslice-method'><b>pieslice(xy, start, end, fill=None, outline=None)</b></a> [<a href='#PIL.ImageDraw.ImageDraw.pieslice-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageDraw.ImageDraw.point-method' name='PIL.ImageDraw.ImageDraw.point-method'><b>point(xy, fill=None)</b></a> [<a href='#PIL.ImageDraw.ImageDraw.point-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageDraw.ImageDraw.polygon-method' name='PIL.ImageDraw.ImageDraw.polygon-method'><b>polygon(xy, fill=None, outline=None)</b></a> [<a href='#PIL.ImageDraw.ImageDraw.polygon-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageDraw.ImageDraw.rectangle-method' name='PIL.ImageDraw.ImageDraw.rectangle-method'><b>rectangle(xy, fill=None, outline=None)</b></a> [<a href='#PIL.ImageDraw.ImageDraw.rectangle-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageDraw.ImageDraw.setfill-method' name='PIL.ImageDraw.ImageDraw.setfill-method'><b>setfill(onoff)</b></a> [<a href='#PIL.ImageDraw.ImageDraw.setfill-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageDraw.ImageDraw.setfont-method' name='PIL.ImageDraw.ImageDraw.setfont-method'><b>setfont(font)</b></a> [<a href='#PIL.ImageDraw.ImageDraw.setfont-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageDraw.ImageDraw.setink-method' name='PIL.ImageDraw.ImageDraw.setink-method'><b>setink(ink)</b></a> [<a href='#PIL.ImageDraw.ImageDraw.setink-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageDraw.ImageDraw.shape-method' name='PIL.ImageDraw.ImageDraw.shape-method'><b>shape(shape, fill=None, outline=None)</b></a> [<a href='#PIL.ImageDraw.ImageDraw.shape-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageDraw.ImageDraw.text-method' name='PIL.ImageDraw.ImageDraw.text-method'><b>text(xy, text, fill=None, font=None, anchor=None)</b></a> [<a href='#PIL.ImageDraw.ImageDraw.text-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageDraw.ImageDraw.textsize-method' name='PIL.ImageDraw.ImageDraw.textsize-method'><b>textsize(text, font=None)</b></a> [<a href='#PIL.ImageDraw.ImageDraw.textsize-method'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImageEnhance.html b/Imaging/Docs/pythondoc-PIL.ImageEnhance.html
new file mode 100644
index 0000000..e7493d0
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImageEnhance.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImageEnhance Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImageEnhance Module</h1>
+<dl>
+<dt><b>Brightness(image)</b> (class) [<a href='#PIL.ImageEnhance.Brightness-class'>#</a>]</dt>
+<dd>
+<p>Brightness enhancement object.</p>
+<p>For more information about this class, see <a href='#PIL.ImageEnhance.Brightness-class'><i>The Brightness Class</i></a>.</p>
+</dd>
+<dt><b>Color(image)</b> (class) [<a href='#PIL.ImageEnhance.Color-class'>#</a>]</dt>
+<dd>
+<p>Color enhancement object.</p>
+<p>For more information about this class, see <a href='#PIL.ImageEnhance.Color-class'><i>The Color Class</i></a>.</p>
+</dd>
+<dt><b>Contrast(image)</b> (class) [<a href='#PIL.ImageEnhance.Contrast-class'>#</a>]</dt>
+<dd>
+<p>Contrast enhancement object.</p>
+<p>For more information about this class, see <a href='#PIL.ImageEnhance.Contrast-class'><i>The Contrast Class</i></a>.</p>
+</dd>
+<dt><b>Sharpness(image)</b> (class) [<a href='#PIL.ImageEnhance.Sharpness-class'>#</a>]</dt>
+<dd>
+<p>Sharpness enhancement object.</p>
+<p>For more information about this class, see <a href='#PIL.ImageEnhance.Sharpness-class'><i>The Sharpness Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.ImageEnhance.Brightness-class' name='PIL.ImageEnhance.Brightness-class'>The Brightness Class</a></h2>
+<dl>
+<dt><b>Brightness(image)</b> (class) [<a href='#PIL.ImageEnhance.Brightness-class'>#</a>]</dt>
+<dd>
+<p>Brightness enhancement object.
+</p><p>
+This class can be used to control the brighntess of an image. An
+enhancement factor of 0.0 gives a black image, factor 1.0 gives the
+original image.
+</p></dd>
+</dl>
+<h2><a id='PIL.ImageEnhance.Color-class' name='PIL.ImageEnhance.Color-class'>The Color Class</a></h2>
+<dl>
+<dt><b>Color(image)</b> (class) [<a href='#PIL.ImageEnhance.Color-class'>#</a>]</dt>
+<dd>
+<p>Color enhancement object.
+</p><p>
+This class can be used to adjust the colour balance of an image, in
+a manner similar to the controls on a colour TV set. An enhancement
+factor of 0.0 gives a black and white image, a factor of 1.0 gives
+the original image.
+</p></dd>
+</dl>
+<h2><a id='PIL.ImageEnhance.Contrast-class' name='PIL.ImageEnhance.Contrast-class'>The Contrast Class</a></h2>
+<dl>
+<dt><b>Contrast(image)</b> (class) [<a href='#PIL.ImageEnhance.Contrast-class'>#</a>]</dt>
+<dd>
+<p>Contrast enhancement object.
+</p><p>
+This class can be used to control the contrast of an image, similar
+to the contrast control on a TV set. An enhancement factor of 0.0
+gives an solid grey image, factor 1.0 gives the original image.
+</p></dd>
+</dl>
+<h2><a id='PIL.ImageEnhance.Sharpness-class' name='PIL.ImageEnhance.Sharpness-class'>The Sharpness Class</a></h2>
+<dl>
+<dt><b>Sharpness(image)</b> (class) [<a href='#PIL.ImageEnhance.Sharpness-class'>#</a>]</dt>
+<dd>
+<p>Sharpness enhancement object.
+</p><p>
+This class can be used to adjust the sharpness of an image. The
+enhancement factor 0.0 gives a blurred image, 1.0 gives the original
+image, and a factor of 2.0 gives a sharpened image.
+</p></dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImageFile.html b/Imaging/Docs/pythondoc-PIL.ImageFile.html
new file mode 100644
index 0000000..6755b69
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImageFile.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImageFile Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImageFile Module</h1>
+<dl>
+<dt><b>_ParserFile(data)</b> (class) [<a href='#PIL.ImageFile._ParserFile-class'>#</a>]</dt>
+<dd>
+<p>(Internal) Support class for the Parser file.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFile._ParserFile-class'><i>The _ParserFile Class</i></a>.</p>
+</dd>
+<dt><a id='PIL.ImageFile._safe_read-function' name='PIL.ImageFile._safe_read-function'><b>_safe_read(fp, size)</b></a> [<a href='#PIL.ImageFile._safe_read-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>fp</i></dt>
+<dd>
+File handle. Must implement a <b>read</b> method.
+</dd>
+<dt><i>size</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+A string containing up to <i>size</i> bytes of data.
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageFile._save-function' name='PIL.ImageFile._save-function'><b>_save(im, fp, tile)</b></a> [<a href='#PIL.ImageFile._save-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>im</i></dt>
+<dd>
+</dd>
+<dt><i>fp</i></dt>
+<dd>
+</dd>
+<dt><i>tile</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><b>ImageFile(fp=None, filename=None)</b> (class) [<a href='#PIL.ImageFile.ImageFile-class'>#</a>]</dt>
+<dd>
+<p>Base class for image file handlers.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFile.ImageFile-class'><i>The ImageFile Class</i></a>.</p>
+</dd>
+<dt><b>Parser</b> (class) [<a href='#PIL.ImageFile.Parser-class'>#</a>]</dt>
+<dd>
+<p>Incremental image parser.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFile.Parser-class'><i>The Parser Class</i></a>.</p>
+</dd>
+<dt><b>StubImageFile</b> (class) [<a href='#PIL.ImageFile.StubImageFile-class'>#</a>]</dt>
+<dd>
+<p>Base class for stub image loaders.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFile.StubImageFile-class'><i>The StubImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.ImageFile._ParserFile-class' name='PIL.ImageFile._ParserFile-class'>The _ParserFile Class</a></h2>
+<dl>
+<dt><b>_ParserFile(data)</b> (class) [<a href='#PIL.ImageFile._ParserFile-class'>#</a>]</dt>
+<dd>
+<p>(Internal) Support class for the <b>Parser</b> file.
+</p></dd>
+</dl>
+<h2><a id='PIL.ImageFile.ImageFile-class' name='PIL.ImageFile.ImageFile-class'>The ImageFile Class</a></h2>
+<dl>
+<dt><b>ImageFile(fp=None, filename=None)</b> (class) [<a href='#PIL.ImageFile.ImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+<h2><a id='PIL.ImageFile.Parser-class' name='PIL.ImageFile.Parser-class'>The Parser Class</a></h2>
+<dl>
+<dt><b>Parser</b> (class) [<a href='#PIL.ImageFile.Parser-class'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageFile.Parser.close-method' name='PIL.ImageFile.Parser.close-method'><b>close()</b></a> [<a href='#PIL.ImageFile.Parser.close-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+<dt>Raises <b>IOError</b>:</dt><dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageFile.Parser.feed-method' name='PIL.ImageFile.Parser.feed-method'><b>feed(data)</b></a> [<a href='#PIL.ImageFile.Parser.feed-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>data</i></dt>
+<dd>
+</dd>
+<dt>Raises <b>IOError</b>:</dt><dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageFile.Parser.reset-method' name='PIL.ImageFile.Parser.reset-method'><b>reset()</b></a> [<a href='#PIL.ImageFile.Parser.reset-method'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+<h2><a id='PIL.ImageFile.StubImageFile-class' name='PIL.ImageFile.StubImageFile-class'>The StubImageFile Class</a></h2>
+<dl>
+<dt><b>StubImageFile</b> (class) [<a href='#PIL.ImageFile.StubImageFile-class'>#</a>]</dt>
+<dd>
+<p>Base class for stub image loaders.
+</p><p>
+A stub loader is an image loader that can identify files of a
+certain format, but relies on external code to load the file.
+</p></dd>
+<dt><a id='PIL.ImageFile.StubImageFile._load-method' name='PIL.ImageFile.StubImageFile._load-method'><b>_load()</b></a> [<a href='#PIL.ImageFile.StubImageFile._load-method'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImageFileIO.html b/Imaging/Docs/pythondoc-PIL.ImageFileIO.html
new file mode 100644
index 0000000..78fc226
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImageFileIO.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImageFileIO Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImageFileIO Module</h1>
+<dl>
+<dt><b>ImageFileIO(fp)</b> (class) [<a href='#PIL.ImageFileIO.ImageFileIO-class'>#</a>]</dt>
+<dd>
+<p>The ImageFileIO module can be used to read an image from a
+socket, or any other stream device.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFileIO.ImageFileIO-class'><i>The ImageFileIO Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.ImageFileIO.ImageFileIO-class' name='PIL.ImageFileIO.ImageFileIO-class'>The ImageFileIO Class</a></h2>
+<dl>
+<dt><b>ImageFileIO(fp)</b> (class) [<a href='#PIL.ImageFileIO.ImageFileIO-class'>#</a>]</dt>
+<dd>
+<p>The <b>ImageFileIO</b> module can be used to read an image from a
+socket, or any other stream device.
+</p><p>
+This module is deprecated. New code should use the <b>Parser</b>
+class in the <a href="imagefile">ImageFile</a> module instead.
+
+</p></dd>
+<dt><a id='PIL.ImageFileIO.ImageFileIO.__init__-method' name='PIL.ImageFileIO.ImageFileIO.__init__-method'><b>__init__(fp)</b></a> [<a href='#PIL.ImageFileIO.ImageFileIO.__init__-method'>#</a>]</dt>
+<dd>
+<p>Adds buffering to a stream file object, in order to
+provide <b>seek</b> and <b>tell</b> methods required
+by the <b>Image.open</b> method. The stream object must
+implement <b>read</b> and <b>close</b> methods.
+
+</p><dl>
+<dt><i>fp</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImageFilter.html b/Imaging/Docs/pythondoc-PIL.ImageFilter.html
new file mode 100644
index 0000000..b67e822
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImageFilter.html
@@ -0,0 +1,257 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImageFilter Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImageFilter Module</h1>
+<dl>
+<dt><b>BLUR</b> (class) [<a href='#PIL.ImageFilter.BLUR-class'>#</a>]</dt>
+<dd>
+<p>Blur filter.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFilter.BLUR-class'><i>The BLUR Class</i></a>.</p>
+</dd>
+<dt><b>CONTOUR</b> (class) [<a href='#PIL.ImageFilter.CONTOUR-class'>#</a>]</dt>
+<dd>
+<p>Contour filter.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFilter.CONTOUR-class'><i>The CONTOUR Class</i></a>.</p>
+</dd>
+<dt><b>DETAIL</b> (class) [<a href='#PIL.ImageFilter.DETAIL-class'>#</a>]</dt>
+<dd>
+<p>Detail filter.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFilter.DETAIL-class'><i>The DETAIL Class</i></a>.</p>
+</dd>
+<dt><b>EDGE_ENHANCE</b> (class) [<a href='#PIL.ImageFilter.EDGE_ENHANCE-class'>#</a>]</dt>
+<dd>
+<p>Edge enhancement filter.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFilter.EDGE_ENHANCE-class'><i>The EDGE_ENHANCE Class</i></a>.</p>
+</dd>
+<dt><b>EDGE_ENHANCE_MORE</b> (class) [<a href='#PIL.ImageFilter.EDGE_ENHANCE_MORE-class'>#</a>]</dt>
+<dd>
+<p>Stronger edge enhancement filter.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFilter.EDGE_ENHANCE_MORE-class'><i>The EDGE_ENHANCE_MORE Class</i></a>.</p>
+</dd>
+<dt><b>EMBOSS</b> (class) [<a href='#PIL.ImageFilter.EMBOSS-class'>#</a>]</dt>
+<dd>
+<p>Embossing filter.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFilter.EMBOSS-class'><i>The EMBOSS Class</i></a>.</p>
+</dd>
+<dt><b>FIND_EDGES</b> (class) [<a href='#PIL.ImageFilter.FIND_EDGES-class'>#</a>]</dt>
+<dd>
+<p>Edge-finding filter.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFilter.FIND_EDGES-class'><i>The FIND_EDGES Class</i></a>.</p>
+</dd>
+<dt><b>Kernel(size, kernel, **options)</b> (class) [<a href='#PIL.ImageFilter.Kernel-class'>#</a>]</dt>
+<dd>
+<p>Convolution filter kernel.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFilter.Kernel-class'><i>The Kernel Class</i></a>.</p>
+</dd>
+<dt><b>MaxFilter(size=3)</b> (class) [<a href='#PIL.ImageFilter.MaxFilter-class'>#</a>]</dt>
+<dd>
+<p>Max filter.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFilter.MaxFilter-class'><i>The MaxFilter Class</i></a>.</p>
+</dd>
+<dt><b>MedianFilter(size=3)</b> (class) [<a href='#PIL.ImageFilter.MedianFilter-class'>#</a>]</dt>
+<dd>
+<p>Median filter.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFilter.MedianFilter-class'><i>The MedianFilter Class</i></a>.</p>
+</dd>
+<dt><b>MinFilter(size=3)</b> (class) [<a href='#PIL.ImageFilter.MinFilter-class'>#</a>]</dt>
+<dd>
+<p>Min filter.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFilter.MinFilter-class'><i>The MinFilter Class</i></a>.</p>
+</dd>
+<dt><b>ModeFilter(size=3)</b> (class) [<a href='#PIL.ImageFilter.ModeFilter-class'>#</a>]</dt>
+<dd>
+<p>Mode filter.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFilter.ModeFilter-class'><i>The ModeFilter Class</i></a>.</p>
+</dd>
+<dt><b>RankFilter(size, rank)</b> (class) [<a href='#PIL.ImageFilter.RankFilter-class'>#</a>]</dt>
+<dd>
+<p>Rank filter.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFilter.RankFilter-class'><i>The RankFilter Class</i></a>.</p>
+</dd>
+<dt><b>SHARPEN</b> (class) [<a href='#PIL.ImageFilter.SHARPEN-class'>#</a>]</dt>
+<dd>
+<p>Sharpening filter.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFilter.SHARPEN-class'><i>The SHARPEN Class</i></a>.</p>
+</dd>
+<dt><b>SMOOTH</b> (class) [<a href='#PIL.ImageFilter.SMOOTH-class'>#</a>]</dt>
+<dd>
+<p>Smoothing filter.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFilter.SMOOTH-class'><i>The SMOOTH Class</i></a>.</p>
+</dd>
+<dt><b>SMOOTH_MORE</b> (class) [<a href='#PIL.ImageFilter.SMOOTH_MORE-class'>#</a>]</dt>
+<dd>
+<p>Stronger smoothing filter.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFilter.SMOOTH_MORE-class'><i>The SMOOTH_MORE Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.ImageFilter.BLUR-class' name='PIL.ImageFilter.BLUR-class'>The BLUR Class</a></h2>
+<dl>
+<dt><b>BLUR</b> (class) [<a href='#PIL.ImageFilter.BLUR-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+<h2><a id='PIL.ImageFilter.CONTOUR-class' name='PIL.ImageFilter.CONTOUR-class'>The CONTOUR Class</a></h2>
+<dl>
+<dt><b>CONTOUR</b> (class) [<a href='#PIL.ImageFilter.CONTOUR-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+<h2><a id='PIL.ImageFilter.DETAIL-class' name='PIL.ImageFilter.DETAIL-class'>The DETAIL Class</a></h2>
+<dl>
+<dt><b>DETAIL</b> (class) [<a href='#PIL.ImageFilter.DETAIL-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+<h2><a id='PIL.ImageFilter.EDGE_ENHANCE-class' name='PIL.ImageFilter.EDGE_ENHANCE-class'>The EDGE_ENHANCE Class</a></h2>
+<dl>
+<dt><b>EDGE_ENHANCE</b> (class) [<a href='#PIL.ImageFilter.EDGE_ENHANCE-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+<h2><a id='PIL.ImageFilter.EDGE_ENHANCE_MORE-class' name='PIL.ImageFilter.EDGE_ENHANCE_MORE-class'>The EDGE_ENHANCE_MORE Class</a></h2>
+<dl>
+<dt><b>EDGE_ENHANCE_MORE</b> (class) [<a href='#PIL.ImageFilter.EDGE_ENHANCE_MORE-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+<h2><a id='PIL.ImageFilter.EMBOSS-class' name='PIL.ImageFilter.EMBOSS-class'>The EMBOSS Class</a></h2>
+<dl>
+<dt><b>EMBOSS</b> (class) [<a href='#PIL.ImageFilter.EMBOSS-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+<h2><a id='PIL.ImageFilter.FIND_EDGES-class' name='PIL.ImageFilter.FIND_EDGES-class'>The FIND_EDGES Class</a></h2>
+<dl>
+<dt><b>FIND_EDGES</b> (class) [<a href='#PIL.ImageFilter.FIND_EDGES-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+<h2><a id='PIL.ImageFilter.Kernel-class' name='PIL.ImageFilter.Kernel-class'>The Kernel Class</a></h2>
+<dl>
+<dt><b>Kernel(size, kernel, **options)</b> (class) [<a href='#PIL.ImageFilter.Kernel-class'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageFilter.Kernel.__init__-method' name='PIL.ImageFilter.Kernel.__init__-method'><b>__init__(size, kernel, **options)</b></a> [<a href='#PIL.ImageFilter.Kernel.__init__-method'>#</a>]</dt>
+<dd>
+<p>Create a convolution kernel. The current version only
+supports 3x3 and 5x5 integer and floating point kernels.
+</p><p>
+In the current version, kernels can only be applied to
+"L" and "RGB" images.
+
+</p><dl>
+<dt><i>size</i></dt>
+<dd>
+</dd>
+<dt><i>kernel</i></dt>
+<dd>
+</dd>
+<dt><i>**options</i></dt>
+<dd>
+</dd>
+<dt><i>scale=</i></dt>
+<dd>
+</dd>
+<dt><i>offset=</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+<h2><a id='PIL.ImageFilter.MaxFilter-class' name='PIL.ImageFilter.MaxFilter-class'>The MaxFilter Class</a></h2>
+<dl>
+<dt><b>MaxFilter(size=3)</b> (class) [<a href='#PIL.ImageFilter.MaxFilter-class'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageFilter.MaxFilter.__init__-method' name='PIL.ImageFilter.MaxFilter.__init__-method'><b>__init__(size=3)</b></a> [<a href='#PIL.ImageFilter.MaxFilter.__init__-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>size</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+<h2><a id='PIL.ImageFilter.MedianFilter-class' name='PIL.ImageFilter.MedianFilter-class'>The MedianFilter Class</a></h2>
+<dl>
+<dt><b>MedianFilter(size=3)</b> (class) [<a href='#PIL.ImageFilter.MedianFilter-class'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageFilter.MedianFilter.__init__-method' name='PIL.ImageFilter.MedianFilter.__init__-method'><b>__init__(size=3)</b></a> [<a href='#PIL.ImageFilter.MedianFilter.__init__-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>size</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+<h2><a id='PIL.ImageFilter.MinFilter-class' name='PIL.ImageFilter.MinFilter-class'>The MinFilter Class</a></h2>
+<dl>
+<dt><b>MinFilter(size=3)</b> (class) [<a href='#PIL.ImageFilter.MinFilter-class'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageFilter.MinFilter.__init__-method' name='PIL.ImageFilter.MinFilter.__init__-method'><b>__init__(size=3)</b></a> [<a href='#PIL.ImageFilter.MinFilter.__init__-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>size</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+<h2><a id='PIL.ImageFilter.ModeFilter-class' name='PIL.ImageFilter.ModeFilter-class'>The ModeFilter Class</a></h2>
+<dl>
+<dt><b>ModeFilter(size=3)</b> (class) [<a href='#PIL.ImageFilter.ModeFilter-class'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageFilter.ModeFilter.__init__-method' name='PIL.ImageFilter.ModeFilter.__init__-method'><b>__init__(size=3)</b></a> [<a href='#PIL.ImageFilter.ModeFilter.__init__-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>size</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+<h2><a id='PIL.ImageFilter.RankFilter-class' name='PIL.ImageFilter.RankFilter-class'>The RankFilter Class</a></h2>
+<dl>
+<dt><b>RankFilter(size, rank)</b> (class) [<a href='#PIL.ImageFilter.RankFilter-class'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageFilter.RankFilter.__init__-method' name='PIL.ImageFilter.RankFilter.__init__-method'><b>__init__(size, rank)</b></a> [<a href='#PIL.ImageFilter.RankFilter.__init__-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>size</i></dt>
+<dd>
+</dd>
+<dt><i>rank</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+<h2><a id='PIL.ImageFilter.SHARPEN-class' name='PIL.ImageFilter.SHARPEN-class'>The SHARPEN Class</a></h2>
+<dl>
+<dt><b>SHARPEN</b> (class) [<a href='#PIL.ImageFilter.SHARPEN-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+<h2><a id='PIL.ImageFilter.SMOOTH-class' name='PIL.ImageFilter.SMOOTH-class'>The SMOOTH Class</a></h2>
+<dl>
+<dt><b>SMOOTH</b> (class) [<a href='#PIL.ImageFilter.SMOOTH-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+<h2><a id='PIL.ImageFilter.SMOOTH_MORE-class' name='PIL.ImageFilter.SMOOTH_MORE-class'>The SMOOTH_MORE Class</a></h2>
+<dl>
+<dt><b>SMOOTH_MORE</b> (class) [<a href='#PIL.ImageFilter.SMOOTH_MORE-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImageFont.html b/Imaging/Docs/pythondoc-PIL.ImageFont.html
new file mode 100644
index 0000000..6f1cd88
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImageFont.html
@@ -0,0 +1,141 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImageFont Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImageFont Module</h1>
+<dl>
+<dt><b>FreeTypeFont(file, size, index=0, encoding=&quot;&quot;)</b> (class) [<a href='#PIL.ImageFont.FreeTypeFont-class'>#</a>]</dt>
+<dd>
+<p>Wrapper for FreeType fonts.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFont.FreeTypeFont-class'><i>The FreeTypeFont Class</i></a>.</p>
+</dd>
+<dt><b>ImageFont</b> (class) [<a href='#PIL.ImageFont.ImageFont-class'>#</a>]</dt>
+<dd>
+<p>The ImageFont module defines a class with the same name.</p>
+<p>For more information about this class, see <a href='#PIL.ImageFont.ImageFont-class'><i>The ImageFont Class</i></a>.</p>
+</dd>
+<dt><a id='PIL.ImageFont.load-function' name='PIL.ImageFont.load-function'><b>load(filename)</b></a> [<a href='#PIL.ImageFont.load-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>filename</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+<dt>Raises <b>IOError</b>:</dt><dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageFont.load_default-function' name='PIL.ImageFont.load_default-function'><b>load_default()</b></a> [<a href='#PIL.ImageFont.load_default-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageFont.load_path-function' name='PIL.ImageFont.load_path-function'><b>load_path(filename)</b></a> [<a href='#PIL.ImageFont.load_path-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>filename</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+<dt>Raises <b>IOError</b>:</dt><dd>
+</dd>
+</dl><br />
+</dd>
+<dt><b>TransposedFont(font, orientation=None)</b> (class) [<a href='#PIL.ImageFont.TransposedFont-class'>#</a>]</dt>
+<dd>
+<p>Wrapper that creates a transposed font from any existing font
+object.</p>
+<dl>
+<dt><i>font</i></dt>
+<dd>
+</dd>
+<dt><i>orientation</i></dt>
+<dd>
+</dd>
+</dl><br />
+<p>For more information about this class, see <a href='#PIL.ImageFont.TransposedFont-class'><i>The TransposedFont Class</i></a>.</p>
+</dd>
+<dt><a id='PIL.ImageFont.truetype-function' name='PIL.ImageFont.truetype-function'><b>truetype(filename, size, index=0, encoding=&quot;&quot;)</b></a> [<a href='#PIL.ImageFont.truetype-function'>#</a>]</dt>
+<dd>
+<p>Load a TrueType or OpenType font file, and create a font object.
+This function loads a font object from the given file, and creates
+a font object for a font of the given size.
+</p><p>
+This function requires the _imagingft service.
+
+</p><dl>
+<dt><i>filename</i></dt>
+<dd>
+A truetype font file. Under Windows, if the file
+ is not found in this filename, the loader also looks in Windows
+ <b>fonts</b> directory
+</dd>
+<dt><i>size</i></dt>
+<dd>
+</dd>
+<dt><i>index</i></dt>
+<dd>
+</dd>
+<dt><i>encoding</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+<dt>Raises <b>IOError</b>:</dt><dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+<h2><a id='PIL.ImageFont.FreeTypeFont-class' name='PIL.ImageFont.FreeTypeFont-class'>The FreeTypeFont Class</a></h2>
+<dl>
+<dt><b>FreeTypeFont(file, size, index=0, encoding=&quot;&quot;)</b> (class) [<a href='#PIL.ImageFont.FreeTypeFont-class'>#</a>]</dt>
+<dd>
+<p>Wrapper for FreeType fonts. Application code should use the
+<b>truetype</b> factory function to create font objects.
+</p></dd>
+</dl>
+<h2><a id='PIL.ImageFont.ImageFont-class' name='PIL.ImageFont.ImageFont-class'>The ImageFont Class</a></h2>
+<dl>
+<dt><b>ImageFont</b> (class) [<a href='#PIL.ImageFont.ImageFont-class'>#</a>]</dt>
+<dd>
+<p>The <b>ImageFont</b> module defines a class with the same name.
+Instances of this class store bitmap fonts, and are used with the
+<b>text</b> method of the <b>ImageDraw</b> class.
+</p><p>
+PIL uses it's own font file format to store bitmap fonts. You can
+use the <b>pilfont</b> utility to convert BDF and PCF font
+descriptors (X window font formats) to this format.
+</p><p>
+Starting with version 1.1.4, PIL can be configured to support
+TrueType and OpenType fonts. For earlier version, TrueType
+support is only available as part of the imToolkit package
+
+</p></dd>
+</dl>
+<h2><a id='PIL.ImageFont.TransposedFont-class' name='PIL.ImageFont.TransposedFont-class'>The TransposedFont Class</a></h2>
+<dl>
+<dt><b>TransposedFont(font, orientation=None)</b> (class) [<a href='#PIL.ImageFont.TransposedFont-class'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>font</i></dt>
+<dd>
+</dd>
+<dt><i>orientation</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImageGL.html b/Imaging/Docs/pythondoc-PIL.ImageGL.html
new file mode 100644
index 0000000..6fee03f
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImageGL.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImageGL Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImageGL Module</h1>
+<h2>Module Contents</h2>
+<dl>
+<dt><b>TextureFactory</b> (class) [<a href='#PIL.ImageGL.TextureFactory-class'>#</a>]</dt>
+<dd>
+<p>Texture factory.</p>
+<p>For more information about this class, see <a href='#PIL.ImageGL.TextureFactory-class'><i>The TextureFactory Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.ImageGL.TextureFactory-class' name='PIL.ImageGL.TextureFactory-class'>The TextureFactory Class</a></h2>
+<dl>
+<dt><b>TextureFactory</b> (class) [<a href='#PIL.ImageGL.TextureFactory-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImageGrab.html b/Imaging/Docs/pythondoc-PIL.ImageGrab.html
new file mode 100644
index 0000000..fb1354e
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImageGrab.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImageGrab Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImageGrab Module</h1>
+<p>(New in 1.1.3) The <b>ImageGrab</b> module can be used to copy
+the contents of the screen to a PIL image memory.
+</p><p>
+The current version works on Windows only.</p>
+
+<h2>Module Contents</h2>
+<dl>
+<dt><a id='PIL.ImageGrab.grab-function' name='PIL.ImageGrab.grab-function'><b>grab(bbox=None)</b></a> [<a href='#PIL.ImageGrab.grab-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>bbox</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageGrab.grabclipboard-function' name='PIL.ImageGrab.grabclipboard-function'><b>grabclipboard()</b></a> [<a href='#PIL.ImageGrab.grabclipboard-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImageOps.html b/Imaging/Docs/pythondoc-PIL.ImageOps.html
new file mode 100644
index 0000000..1554571
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImageOps.html
@@ -0,0 +1,221 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImageOps Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImageOps Module</h1>
+<p>(New in 1.1.3) The <b>ImageOps</b> module contains a number of
+'ready-made' image processing operations. This module is somewhat
+experimental, and most operators only work on L and RGB images.
+
+</p><h2>Module Contents</h2>
+<dl>
+<dt><a id='PIL.ImageOps.autocontrast-function' name='PIL.ImageOps.autocontrast-function'><b>autocontrast(image, cutoff=0, ignore=None)</b></a> [<a href='#PIL.ImageOps.autocontrast-function'>#</a>]</dt>
+<dd>
+<p>Maximize (normalize) image contrast. This function calculates a
+histogram of the input image, removes <i>cutoff</i> percent of the
+lightest and darkest pixels from the histogram, and remaps the image
+so that the darkest pixel becomes black (0), and the lightest
+becomes white (255).
+
+</p><dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt><i>cutoff</i></dt>
+<dd>
+</dd>
+<dt><i>ignore</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageOps.colorize-function' name='PIL.ImageOps.colorize-function'><b>colorize(image, black, white)</b></a> [<a href='#PIL.ImageOps.colorize-function'>#</a>]</dt>
+<dd>
+<p>Colorize grayscale image. The <i>black</i> and <i>white</i>
+arguments should be RGB tuples; this function calculates a colour
+wedge mapping all black pixels in the source image to the first
+colour, and all white pixels to the second colour.
+
+</p><dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt><i>black</i></dt>
+<dd>
+</dd>
+<dt><i>white</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageOps.crop-function' name='PIL.ImageOps.crop-function'><b>crop(image, border=0)</b></a> [<a href='#PIL.ImageOps.crop-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt><i>border</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageOps.deform-function' name='PIL.ImageOps.deform-function'><b>deform(image, deformer, resample=Image.BILINEAR)</b></a> [<a href='#PIL.ImageOps.deform-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt><i>deformer</i></dt>
+<dd>
+</dd>
+<dt><i>resample</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageOps.equalize-function' name='PIL.ImageOps.equalize-function'><b>equalize(image, mask=None)</b></a> [<a href='#PIL.ImageOps.equalize-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt><i>mask</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageOps.expand-function' name='PIL.ImageOps.expand-function'><b>expand(image, border=0, fill=0)</b></a> [<a href='#PIL.ImageOps.expand-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt><i>border</i></dt>
+<dd>
+</dd>
+<dt><i>fill</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageOps.fit-function' name='PIL.ImageOps.fit-function'><b>fit(image, size, method=Image.NEAREST, bleed=0.0, centering=(0.5, 0.5))</b></a> [<a href='#PIL.ImageOps.fit-function'>#</a>]</dt>
+<dd>
+<p>Returns a sized and cropped version of the image, cropped to the
+requested aspect ratio and size.
+</p><p>
+The <b>fit</b> function was contributed by Kevin Cazabon.
+
+</p><dl>
+<dt><i>size</i></dt>
+<dd>
+</dd>
+<dt><i>method</i></dt>
+<dd>
+</dd>
+<dt><i>bleed</i></dt>
+<dd>
+</dd>
+<dt><i>centering</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageOps.flip-function' name='PIL.ImageOps.flip-function'><b>flip(image)</b></a> [<a href='#PIL.ImageOps.flip-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageOps.grayscale-function' name='PIL.ImageOps.grayscale-function'><b>grayscale(image)</b></a> [<a href='#PIL.ImageOps.grayscale-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageOps.invert-function' name='PIL.ImageOps.invert-function'><b>invert(image)</b></a> [<a href='#PIL.ImageOps.invert-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageOps.mirror-function' name='PIL.ImageOps.mirror-function'><b>mirror(image)</b></a> [<a href='#PIL.ImageOps.mirror-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageOps.posterize-function' name='PIL.ImageOps.posterize-function'><b>posterize(image, bits)</b></a> [<a href='#PIL.ImageOps.posterize-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt><i>bits</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageOps.solarize-function' name='PIL.ImageOps.solarize-function'><b>solarize(image, threshold=128)</b></a> [<a href='#PIL.ImageOps.solarize-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt><i>threshold</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImagePalette.html b/Imaging/Docs/pythondoc-PIL.ImagePalette.html
new file mode 100644
index 0000000..67e0d11
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImagePalette.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImagePalette Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImagePalette Module</h1>
+<dl>
+<dt><b>ImagePalette(mode=&quot;RGB&quot;, palette=None)</b> (class) [<a href='#PIL.ImagePalette.ImagePalette-class'>#</a>]</dt>
+<dd>
+<p>Colour palette wrapper for palette mapped images.</p>
+<p>For more information about this class, see <a href='#PIL.ImagePalette.ImagePalette-class'><i>The ImagePalette Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.ImagePalette.ImagePalette-class' name='PIL.ImagePalette.ImagePalette-class'>The ImagePalette Class</a></h2>
+<dl>
+<dt><b>ImagePalette(mode=&quot;RGB&quot;, palette=None)</b> (class) [<a href='#PIL.ImagePalette.ImagePalette-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImagePath.html b/Imaging/Docs/pythondoc-PIL.ImagePath.html
new file mode 100644
index 0000000..67743bd
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImagePath.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImagePath Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImagePath Module</h1>
+<dl>
+<dt><b>Path(xy)</b> (class) [<a href='#PIL.ImagePath.Path-class'>#</a>]</dt>
+<dd>
+<p>Path wrapper.</p>
+<p>For more information about this class, see <a href='#PIL.ImagePath.Path-class'><i>The Path Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.ImagePath.Path-class' name='PIL.ImagePath.Path-class'>The Path Class</a></h2>
+<dl>
+<dt><b>Path(xy)</b> (class) [<a href='#PIL.ImagePath.Path-class'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImagePath.Path.__init__-method' name='PIL.ImagePath.Path.__init__-method'><b>__init__(xy)</b></a> [<a href='#PIL.ImagePath.Path.__init__-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>xy</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImagePath.Path.compact-method' name='PIL.ImagePath.Path.compact-method'><b>compact(distance=2)</b></a> [<a href='#PIL.ImagePath.Path.compact-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImagePath.Path.getbbox-method' name='PIL.ImagePath.Path.getbbox-method'><b>getbbox()</b></a> [<a href='#PIL.ImagePath.Path.getbbox-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImagePath.Path.map-method' name='PIL.ImagePath.Path.map-method'><b>map(function)</b></a> [<a href='#PIL.ImagePath.Path.map-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImagePath.Path.tolist-method' name='PIL.ImagePath.Path.tolist-method'><b>tolist(flat=0)</b></a> [<a href='#PIL.ImagePath.Path.tolist-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>flat</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImagePath.Path.transform-method' name='PIL.ImagePath.Path.transform-method'><b>transform(matrix)</b></a> [<a href='#PIL.ImagePath.Path.transform-method'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImageSequence.html b/Imaging/Docs/pythondoc-PIL.ImageSequence.html
new file mode 100644
index 0000000..848e7a2
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImageSequence.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImageSequence Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImageSequence Module</h1>
+<dl>
+<dt><b>Iterator(im)</b> (class) [<a href='#PIL.ImageSequence.Iterator-class'>#</a>]</dt>
+<dd>
+<p>This class implements an iterator object that can be used to loop
+over an image sequence.</p>
+<p>For more information about this class, see <a href='#PIL.ImageSequence.Iterator-class'><i>The Iterator Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.ImageSequence.Iterator-class' name='PIL.ImageSequence.Iterator-class'>The Iterator Class</a></h2>
+<dl>
+<dt><b>Iterator(im)</b> (class) [<a href='#PIL.ImageSequence.Iterator-class'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageSequence.Iterator.__init__-method' name='PIL.ImageSequence.Iterator.__init__-method'><b>__init__(im)</b></a> [<a href='#PIL.ImageSequence.Iterator.__init__-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>im</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImageStat.html b/Imaging/Docs/pythondoc-PIL.ImageStat.html
new file mode 100644
index 0000000..10a308b
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImageStat.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImageStat Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImageStat Module</h1>
+<p>The <b>ImageStat</b> module calculates global statistics for an
+image, or a region of an image.
+</p><h2>Module Contents</h2>
+<dl>
+<dt><b>Stat(image, mask=None)</b> (class) [<a href='#PIL.ImageStat.Stat-class'>#</a>]</dt>
+<dd>
+<p>Calculate statistics for the given image.</p>
+<p>For more information about this class, see <a href='#PIL.ImageStat.Stat-class'><i>The Stat Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.ImageStat.Stat-class' name='PIL.ImageStat.Stat-class'>The Stat Class</a></h2>
+<dl>
+<dt><b>Stat(image, mask=None)</b> (class) [<a href='#PIL.ImageStat.Stat-class'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageStat.Stat.__init__-method' name='PIL.ImageStat.Stat.__init__-method'><b>__init__(image, mask=None)</b></a> [<a href='#PIL.ImageStat.Stat.__init__-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt><i>mask</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImageTk.html b/Imaging/Docs/pythondoc-PIL.ImageTk.html
new file mode 100644
index 0000000..d5d4e23
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImageTk.html
@@ -0,0 +1,141 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImageTk Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImageTk Module</h1>
+<p>The <b>ImageTk</b> module contains support to create and modify
+Tkinter <b>BitmapImage</b> and <b>PhotoImage</b> objects.
+</p><p>
+For examples, see the demo programs in the <i>Scripts</i>
+directory.
+</p><h2>Module Contents</h2>
+<dl>
+<dt><b>BitmapImage(image=None, **options)</b> (class) [<a href='#PIL.ImageTk.BitmapImage-class'>#</a>]</dt>
+<dd>
+<p>Create a Tkinter-compatible bitmap image.</p>
+<p>For more information about this class, see <a href='#PIL.ImageTk.BitmapImage-class'><i>The BitmapImage Class</i></a>.</p>
+</dd>
+<dt><a id='PIL.ImageTk.getimage-function' name='PIL.ImageTk.getimage-function'><b>getimage(photo)</b></a> [<a href='#PIL.ImageTk.getimage-function'>#</a>]</dt>
+<dd>
+</dd>
+<dt><b>PhotoImage(image=None, size=None, **options)</b> (class) [<a href='#PIL.ImageTk.PhotoImage-class'>#</a>]</dt>
+<dd>
+<p>Creates a Tkinter-compatible photo image.</p>
+<p>For more information about this class, see <a href='#PIL.ImageTk.PhotoImage-class'><i>The PhotoImage Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.ImageTk.BitmapImage-class' name='PIL.ImageTk.BitmapImage-class'>The BitmapImage Class</a></h2>
+<dl>
+<dt><b>BitmapImage(image=None, **options)</b> (class) [<a href='#PIL.ImageTk.BitmapImage-class'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageTk.BitmapImage.__init__-method' name='PIL.ImageTk.BitmapImage.__init__-method'><b>__init__(image=None, **options)</b></a> [<a href='#PIL.ImageTk.BitmapImage.__init__-method'>#</a>]</dt>
+<dd>
+<p>Create a Tkinter-compatible bitmap image.
+</p><p>
+The given image must have mode "1". Pixels having value 0 are
+treated as transparent. Options, if any, are passed on to
+Tkinter. The most commonly used option is <b>foreground</b>,
+which is used to specify the colour for the non-transparent
+parts. See the Tkinter documentation for information on how to
+specify colours.
+
+</p><dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageTk.BitmapImage.__str__-method' name='PIL.ImageTk.BitmapImage.__str__-method'><b>__str__()</b></a> [<a href='#PIL.ImageTk.BitmapImage.__str__-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageTk.BitmapImage.height-method' name='PIL.ImageTk.BitmapImage.height-method'><b>height()</b></a> [<a href='#PIL.ImageTk.BitmapImage.height-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageTk.BitmapImage.width-method' name='PIL.ImageTk.BitmapImage.width-method'><b>width()</b></a> [<a href='#PIL.ImageTk.BitmapImage.width-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+<h2><a id='PIL.ImageTk.PhotoImage-class' name='PIL.ImageTk.PhotoImage-class'>The PhotoImage Class</a></h2>
+<dl>
+<dt><b>PhotoImage(image=None, size=None, **options)</b> (class) [<a href='#PIL.ImageTk.PhotoImage-class'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.ImageTk.PhotoImage.__init__-method' name='PIL.ImageTk.PhotoImage.__init__-method'><b>__init__(image=None, size=None, **options)</b></a> [<a href='#PIL.ImageTk.PhotoImage.__init__-method'>#</a>]</dt>
+<dd>
+<p>Create a photo image object. The constructor takes either
+a PIL image, or a mode and a size. Alternatively, you can
+use the <b>file</b> or <b>data</b> options to initialize
+the photo image object.
+</p><p>
+</p><dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt><i>size</i></dt>
+<dd>
+</dd>
+<dt><i>file=</i></dt>
+<dd>
+</dd>
+<dt><i>data=</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageTk.PhotoImage.__str__-method' name='PIL.ImageTk.PhotoImage.__str__-method'><b>__str__()</b></a> [<a href='#PIL.ImageTk.PhotoImage.__str__-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageTk.PhotoImage.height-method' name='PIL.ImageTk.PhotoImage.height-method'><b>height()</b></a> [<a href='#PIL.ImageTk.PhotoImage.height-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageTk.PhotoImage.paste-method' name='PIL.ImageTk.PhotoImage.paste-method'><b>paste(im, box=None)</b></a> [<a href='#PIL.ImageTk.PhotoImage.paste-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>im</i></dt>
+<dd>
+</dd>
+<dt><i>box</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageTk.PhotoImage.width-method' name='PIL.ImageTk.PhotoImage.width-method'><b>width()</b></a> [<a href='#PIL.ImageTk.PhotoImage.width-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImageTransform.html b/Imaging/Docs/pythondoc-PIL.ImageTransform.html
new file mode 100644
index 0000000..6771fb1
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImageTransform.html
@@ -0,0 +1,140 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImageTransform Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImageTransform Module</h1>
+<dl>
+<dt><b>AffineTransform</b> (class) [<a href='#PIL.ImageTransform.AffineTransform-class'>#</a>]</dt>
+<dd>
+<p>Define an affine image transform.</p>
+<dl>
+<dt><i>matrix</i></dt>
+<dd>
+A 6-tuple (<i>a, b, c, d, e, f</i>) containing
+ the first two rows from an affine transform matrix.
+</dd>
+</dl><br />
+<p>For more information about this class, see <a href='#PIL.ImageTransform.AffineTransform-class'><i>The AffineTransform Class</i></a>.</p>
+</dd>
+<dt><b>ExtentTransform</b> (class) [<a href='#PIL.ImageTransform.ExtentTransform-class'>#</a>]</dt>
+<dd>
+<p>Define a transform to extract a subregion from an image.</p>
+<dl>
+<dt><i>bbox</i></dt>
+<dd>
+A 4-tuple (<i>x0, y0, x1, y1</i>) which specifies
+ two points in the input image's coordinate system.
+</dd>
+</dl><br />
+<p>For more information about this class, see <a href='#PIL.ImageTransform.ExtentTransform-class'><i>The ExtentTransform Class</i></a>.</p>
+</dd>
+<dt><b>MeshTransform</b> (class) [<a href='#PIL.ImageTransform.MeshTransform-class'>#</a>]</dt>
+<dd>
+<p>Define an mesh image transform.</p>
+<dl>
+<dt><i>data</i></dt>
+<dd>
+</dd>
+</dl><br />
+<p>For more information about this class, see <a href='#PIL.ImageTransform.MeshTransform-class'><i>The MeshTransform Class</i></a>.</p>
+</dd>
+<dt><b>QuadTransform</b> (class) [<a href='#PIL.ImageTransform.QuadTransform-class'>#</a>]</dt>
+<dd>
+<p>Define an quad image transform.</p>
+<dl>
+<dt><i>xy</i></dt>
+<dd>
+An 8-tuple (<i>x0, y0, x1, y1, x2, y2, y3, y3</i>) which
+ contain the upper left, lower left, lower right, and upper right
+ corner of the source quadrilateral.
+</dd>
+</dl><br />
+<p>For more information about this class, see <a href='#PIL.ImageTransform.QuadTransform-class'><i>The QuadTransform Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.ImageTransform.AffineTransform-class' name='PIL.ImageTransform.AffineTransform-class'>The AffineTransform Class</a></h2>
+<dl>
+<dt><b>AffineTransform</b> (class) [<a href='#PIL.ImageTransform.AffineTransform-class'>#</a>]</dt>
+<dd>
+<p>Define an affine image transform.
+</p><p>
+This function takes a 6-tuple (<i>a, b, c, d, e, f</i>) which
+contain the first two rows from an affine transform matrix. For
+each pixel (<i>x, y</i>) in the output image, the new value is
+taken from a position (a <i>x</i> + b <i>y</i> + c,
+d <i>x</i> + e <i>y</i> + f) in the input image, rounded to
+nearest pixel.
+</p><p>
+This function can be used to scale, translate, rotate, and shear the
+original image.
+
+</p><dl>
+<dt><i>matrix</i></dt>
+<dd>
+A 6-tuple (<i>a, b, c, d, e, f</i>) containing
+ the first two rows from an affine transform matrix.
+</dd>
+</dl><br />
+</dd>
+</dl>
+<h2><a id='PIL.ImageTransform.ExtentTransform-class' name='PIL.ImageTransform.ExtentTransform-class'>The ExtentTransform Class</a></h2>
+<dl>
+<dt><b>ExtentTransform</b> (class) [<a href='#PIL.ImageTransform.ExtentTransform-class'>#</a>]</dt>
+<dd>
+<p>Define a transform to extract a subregion from an image.
+</p><p>
+Maps a rectangle (defined by two corners) from the image to a
+rectangle of the given size. The resulting image will contain
+data sampled from between the corners, such that (<i>x0, y0</i>)
+in the input image will end up at (0,0) in the output image,
+and (<i>x1, y1</i>) at <i>size</i>.
+</p><p>
+This method can be used to crop, stretch, shrink, or mirror an
+arbitrary rectangle in the current image. It is slightly slower than
+<b>crop</b>, but about as fast as a corresponding <b>resize</b>
+operation.
+
+</p><dl>
+<dt><i>bbox</i></dt>
+<dd>
+A 4-tuple (<i>x0, y0, x1, y1</i>) which specifies
+ two points in the input image's coordinate system.
+</dd>
+</dl><br />
+</dd>
+</dl>
+<h2><a id='PIL.ImageTransform.MeshTransform-class' name='PIL.ImageTransform.MeshTransform-class'>The MeshTransform Class</a></h2>
+<dl>
+<dt><b>MeshTransform</b> (class) [<a href='#PIL.ImageTransform.MeshTransform-class'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>data</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+<h2><a id='PIL.ImageTransform.QuadTransform-class' name='PIL.ImageTransform.QuadTransform-class'>The QuadTransform Class</a></h2>
+<dl>
+<dt><b>QuadTransform</b> (class) [<a href='#PIL.ImageTransform.QuadTransform-class'>#</a>]</dt>
+<dd>
+<p>Define an quad image transform.
+</p><p>
+Maps a quadrilateral (a region defined by four corners) from the
+image to a rectangle of the given size.
+
+</p><dl>
+<dt><i>xy</i></dt>
+<dd>
+An 8-tuple (<i>x0, y0, x1, y1, x2, y2, y3, y3</i>) which
+ contain the upper left, lower left, lower right, and upper right
+ corner of the source quadrilateral.
+</dd>
+</dl><br />
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImageWin.html b/Imaging/Docs/pythondoc-PIL.ImageWin.html
new file mode 100644
index 0000000..e1608d1
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImageWin.html
@@ -0,0 +1,141 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImageWin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImageWin Module</h1>
+<dl>
+<dt><b>Dib(image, size=None)</b> (class) [<a href='#PIL.ImageWin.Dib-class'>#</a>]</dt>
+<dd>
+<p>Create a Windows bitmap with the given mode and size.</p>
+<p>For more information about this class, see <a href='#PIL.ImageWin.Dib-class'><i>The Dib Class</i></a>.</p>
+</dd>
+<dt><b>HDC(dc)</b> (class) [<a href='#PIL.ImageWin.HDC-class'>#</a>]</dt>
+<dd>
+<p>The ImageWin module contains support to create and display
+images under Windows 95/98, NT, 2000 and later.</p>
+<p>For more information about this class, see <a href='#PIL.ImageWin.HDC-class'><i>The HDC Class</i></a>.</p>
+</dd>
+<dt><b>ImageWindow(image, title=&quot;PIL&quot;)</b> (class) [<a href='#PIL.ImageWin.ImageWindow-class'>#</a>]</dt>
+<dd>
+<p>Create an image window which displays the given image.</p>
+<p>For more information about this class, see <a href='#PIL.ImageWin.ImageWindow-class'><i>The ImageWindow Class</i></a>.</p>
+</dd>
+<dt><b>Window(title=&quot;PIL&quot;, width=None, height=None)</b> (class) [<a href='#PIL.ImageWin.Window-class'>#</a>]</dt>
+<dd>
+<p>Create a Window with the given title size.</p>
+<p>For more information about this class, see <a href='#PIL.ImageWin.Window-class'><i>The Window Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.ImageWin.Dib-class' name='PIL.ImageWin.Dib-class'>The Dib Class</a></h2>
+<dl>
+<dt><b>Dib(image, size=None)</b> (class) [<a href='#PIL.ImageWin.Dib-class'>#</a>]</dt>
+<dd>
+<p>Create a Windows bitmap with the given mode and size. The mode can
+be one of "1", "L", "P", or "RGB".
+
+If the display requires a palette, this constructor creates a
+suitable palette and associates it with the image. For an "L" image,
+128 greylevels are allocated. For an "RGB" image, a 6x6x6 colour
+cube is used, together with 20 greylevels.
+
+To make sure that palettes work properly under Windows, you must
+call the <b>palette</b> method upon certain events from Windows.
+</p></dd>
+<dt><a id='PIL.ImageWin.Dib.__init__-method' name='PIL.ImageWin.Dib.__init__-method'><b>__init__(image, size=None)</b></a> [<a href='#PIL.ImageWin.Dib.__init__-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>image</i></dt>
+<dd>
+</dd>
+<dt><i>size</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageWin.Dib.expose-method' name='PIL.ImageWin.Dib.expose-method'><b>expose(handle)</b></a> [<a href='#PIL.ImageWin.Dib.expose-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>handle</i></dt>
+<dd>
+Device context (HDC), cast to a Python integer,
+ or a HDC or HWND instance. In PythonWin, you can use the
+ <b>GetHandleAttrib</b> method of the <b>CDC</b> class to get
+ a suitable handle.
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageWin.Dib.fromstring-method' name='PIL.ImageWin.Dib.fromstring-method'><b>fromstring(buffer)</b></a> [<a href='#PIL.ImageWin.Dib.fromstring-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>buffer</i></dt>
+<dd>
+A string buffer containing display data (usually
+ data returned from <b>tostring</b>)
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageWin.Dib.paste-method' name='PIL.ImageWin.Dib.paste-method'><b>paste(im, box=None)</b></a> [<a href='#PIL.ImageWin.Dib.paste-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>im</i></dt>
+<dd>
+</dd>
+<dt><i>box</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageWin.Dib.query_palette-method' name='PIL.ImageWin.Dib.query_palette-method'><b>query_palette(handle)</b></a> [<a href='#PIL.ImageWin.Dib.query_palette-method'>#</a>]</dt>
+<dd>
+<p>Installs the palette associated with the image in the
+given device context.
+</p><p>
+This method should be called upon <b>QUERYNEWPALETTE</b>
+and <b>PALETTECHANGED</b> events from Windows. If this
+method returns a non-zero value, one or more display
+palette entries were changed, and the image should be
+redrawn.
+
+</p><dl>
+<dt><i>handle</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><a id='PIL.ImageWin.Dib.tostring-method' name='PIL.ImageWin.Dib.tostring-method'><b>tostring()</b></a> [<a href='#PIL.ImageWin.Dib.tostring-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+<h2><a id='PIL.ImageWin.HDC-class' name='PIL.ImageWin.HDC-class'>The HDC Class</a></h2>
+<dl>
+<dt><b>HDC(dc)</b> (class) [<a href='#PIL.ImageWin.HDC-class'>#</a>]</dt>
+<dd>
+<p>The <b>ImageWin</b> module contains support to create and display
+images under Windows 95/98, NT, 2000 and later.
+</p></dd>
+</dl>
+<h2><a id='PIL.ImageWin.ImageWindow-class' name='PIL.ImageWin.ImageWindow-class'>The ImageWindow Class</a></h2>
+<dl>
+<dt><b>ImageWindow(image, title=&quot;PIL&quot;)</b> (class) [<a href='#PIL.ImageWin.ImageWindow-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+<h2><a id='PIL.ImageWin.Window-class' name='PIL.ImageWin.Window-class'>The Window Class</a></h2>
+<dl>
+<dt><b>Window(title=&quot;PIL&quot;, width=None, height=None)</b> (class) [<a href='#PIL.ImageWin.Window-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.ImtImagePlugin.html b/Imaging/Docs/pythondoc-PIL.ImtImagePlugin.html
new file mode 100644
index 0000000..7f20714
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.ImtImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.ImtImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.ImtImagePlugin Module</h1>
+<dl>
+<dt><b>ImtImageFile</b> (class) [<a href='#PIL.ImtImagePlugin.ImtImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for IM Tools images.</p>
+<p>For more information about this class, see <a href='#PIL.ImtImagePlugin.ImtImageFile-class'><i>The ImtImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.ImtImagePlugin.ImtImageFile-class' name='PIL.ImtImagePlugin.ImtImageFile-class'>The ImtImageFile Class</a></h2>
+<dl>
+<dt><b>ImtImageFile</b> (class) [<a href='#PIL.ImtImagePlugin.ImtImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.IptcImagePlugin.html b/Imaging/Docs/pythondoc-PIL.IptcImagePlugin.html
new file mode 100644
index 0000000..fe50303
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.IptcImagePlugin.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.IptcImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.IptcImagePlugin Module</h1>
+<dl>
+<dt><a id='PIL.IptcImagePlugin.getiptcinfo-function' name='PIL.IptcImagePlugin.getiptcinfo-function'><b>getiptcinfo(im)</b></a> [<a href='#PIL.IptcImagePlugin.getiptcinfo-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>im</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><b>IptcImageFile</b> (class) [<a href='#PIL.IptcImagePlugin.IptcImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for IPTC/NAA datastreams.</p>
+<p>For more information about this class, see <a href='#PIL.IptcImagePlugin.IptcImageFile-class'><i>The IptcImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.IptcImagePlugin.IptcImageFile-class' name='PIL.IptcImagePlugin.IptcImageFile-class'>The IptcImageFile Class</a></h2>
+<dl>
+<dt><b>IptcImageFile</b> (class) [<a href='#PIL.IptcImagePlugin.IptcImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for IPTC/NAA datastreams. To read IPTC/NAA fields
+from TIFF and JPEG files, use the <b>getiptcinfo</b> function.
+</p></dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.JpegImagePlugin.html b/Imaging/Docs/pythondoc-PIL.JpegImagePlugin.html
new file mode 100644
index 0000000..fc19e7c
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.JpegImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.JpegImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.JpegImagePlugin Module</h1>
+<dl>
+<dt><b>JpegImageFile</b> (class) [<a href='#PIL.JpegImagePlugin.JpegImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for JPEG and JFIF images.</p>
+<p>For more information about this class, see <a href='#PIL.JpegImagePlugin.JpegImageFile-class'><i>The JpegImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.JpegImagePlugin.JpegImageFile-class' name='PIL.JpegImagePlugin.JpegImageFile-class'>The JpegImageFile Class</a></h2>
+<dl>
+<dt><b>JpegImageFile</b> (class) [<a href='#PIL.JpegImagePlugin.JpegImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.McIdasImagePlugin.html b/Imaging/Docs/pythondoc-PIL.McIdasImagePlugin.html
new file mode 100644
index 0000000..a595303
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.McIdasImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.McIdasImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.McIdasImagePlugin Module</h1>
+<dl>
+<dt><b>McIdasImageFile</b> (class) [<a href='#PIL.McIdasImagePlugin.McIdasImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for McIdas area images.</p>
+<p>For more information about this class, see <a href='#PIL.McIdasImagePlugin.McIdasImageFile-class'><i>The McIdasImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.McIdasImagePlugin.McIdasImageFile-class' name='PIL.McIdasImagePlugin.McIdasImageFile-class'>The McIdasImageFile Class</a></h2>
+<dl>
+<dt><b>McIdasImageFile</b> (class) [<a href='#PIL.McIdasImagePlugin.McIdasImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.MicImagePlugin.html b/Imaging/Docs/pythondoc-PIL.MicImagePlugin.html
new file mode 100644
index 0000000..fdd7467
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.MicImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.MicImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.MicImagePlugin Module</h1>
+<dl>
+<dt><b>MicImageFile</b> (class) [<a href='#PIL.MicImagePlugin.MicImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for Microsoft's Image Composer file format.</p>
+<p>For more information about this class, see <a href='#PIL.MicImagePlugin.MicImageFile-class'><i>The MicImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.MicImagePlugin.MicImageFile-class' name='PIL.MicImagePlugin.MicImageFile-class'>The MicImageFile Class</a></h2>
+<dl>
+<dt><b>MicImageFile</b> (class) [<a href='#PIL.MicImagePlugin.MicImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.MpegImagePlugin.html b/Imaging/Docs/pythondoc-PIL.MpegImagePlugin.html
new file mode 100644
index 0000000..b40d0c2
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.MpegImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.MpegImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.MpegImagePlugin Module</h1>
+<dl>
+<dt><b>MpegImageFile</b> (class) [<a href='#PIL.MpegImagePlugin.MpegImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for MPEG streams.</p>
+<p>For more information about this class, see <a href='#PIL.MpegImagePlugin.MpegImageFile-class'><i>The MpegImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.MpegImagePlugin.MpegImageFile-class' name='PIL.MpegImagePlugin.MpegImageFile-class'>The MpegImageFile Class</a></h2>
+<dl>
+<dt><b>MpegImageFile</b> (class) [<a href='#PIL.MpegImagePlugin.MpegImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.MspImagePlugin.html b/Imaging/Docs/pythondoc-PIL.MspImagePlugin.html
new file mode 100644
index 0000000..c17e991
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.MspImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.MspImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.MspImagePlugin Module</h1>
+<dl>
+<dt><b>MspImageFile</b> (class) [<a href='#PIL.MspImagePlugin.MspImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for Windows MSP images.</p>
+<p>For more information about this class, see <a href='#PIL.MspImagePlugin.MspImageFile-class'><i>The MspImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.MspImagePlugin.MspImageFile-class' name='PIL.MspImagePlugin.MspImageFile-class'>The MspImageFile Class</a></h2>
+<dl>
+<dt><b>MspImageFile</b> (class) [<a href='#PIL.MspImagePlugin.MspImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.OleFileIO.html b/Imaging/Docs/pythondoc-PIL.OleFileIO.html
new file mode 100644
index 0000000..f56a6b4
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.OleFileIO.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.OleFileIO Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.OleFileIO Module</h1>
+<dl>
+<dt><b>OleFileIO(filename=None)</b> (class) [<a href='#PIL.OleFileIO.OleFileIO-class'>#</a>]</dt>
+<dd>
+<p>This class encapsulates the interface to an OLE 2 structured
+storage file.</p>
+<p>For more information about this class, see <a href='#PIL.OleFileIO.OleFileIO-class'><i>The OleFileIO Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.OleFileIO.OleFileIO-class' name='PIL.OleFileIO.OleFileIO-class'>The OleFileIO Class</a></h2>
+<dl>
+<dt><b>OleFileIO(filename=None)</b> (class) [<a href='#PIL.OleFileIO.OleFileIO-class'>#</a>]</dt>
+<dd>
+<p>This class encapsulates the interface to an OLE 2 structured
+storage file. Use the <a class="link" href="link:listdir"><b>listdir</b></a> and <a class="link" href="link:openstream"><b>openstream</b></a>
+methods to access the contents of this file.
+</p></dd>
+<dt><a id='PIL.OleFileIO.OleFileIO.getproperties-method' name='PIL.OleFileIO.OleFileIO.getproperties-method'><b>getproperties(filename)</b></a> [<a href='#PIL.OleFileIO.OleFileIO.getproperties-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.OleFileIO.OleFileIO.listdir-method' name='PIL.OleFileIO.OleFileIO.listdir-method'><b>listdir()</b></a> [<a href='#PIL.OleFileIO.OleFileIO.listdir-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.OleFileIO.OleFileIO.open-method' name='PIL.OleFileIO.OleFileIO.open-method'><b>open(filename)</b></a> [<a href='#PIL.OleFileIO.OleFileIO.open-method'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.OleFileIO.OleFileIO.openstream-method' name='PIL.OleFileIO.OleFileIO.openstream-method'><b>openstream(filename)</b></a> [<a href='#PIL.OleFileIO.OleFileIO.openstream-method'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.PSDraw.html b/Imaging/Docs/pythondoc-PIL.PSDraw.html
new file mode 100644
index 0000000..f89d796
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.PSDraw.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.PSDraw Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.PSDraw Module</h1>
+<dl>
+<dt><b>PSDraw(fp=None)</b> (class) [<a href='#PIL.PSDraw.PSDraw-class'>#</a>]</dt>
+<dd>
+<p>Simple Postscript graphics interface.</p>
+<p>For more information about this class, see <a href='#PIL.PSDraw.PSDraw-class'><i>The PSDraw Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.PSDraw.PSDraw-class' name='PIL.PSDraw.PSDraw-class'>The PSDraw Class</a></h2>
+<dl>
+<dt><b>PSDraw(fp=None)</b> (class) [<a href='#PIL.PSDraw.PSDraw-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.PaletteFile.html b/Imaging/Docs/pythondoc-PIL.PaletteFile.html
new file mode 100644
index 0000000..65e4de4
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.PaletteFile.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.PaletteFile Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.PaletteFile Module</h1>
+<dl>
+<dt><b>PaletteFile(fp)</b> (class) [<a href='#PIL.PaletteFile.PaletteFile-class'>#</a>]</dt>
+<dd>
+<p>File handler for Teragon-style palette files.</p>
+<p>For more information about this class, see <a href='#PIL.PaletteFile.PaletteFile-class'><i>The PaletteFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.PaletteFile.PaletteFile-class' name='PIL.PaletteFile.PaletteFile-class'>The PaletteFile Class</a></h2>
+<dl>
+<dt><b>PaletteFile(fp)</b> (class) [<a href='#PIL.PaletteFile.PaletteFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.PalmImagePlugin.html b/Imaging/Docs/pythondoc-PIL.PalmImagePlugin.html
new file mode 100644
index 0000000..d5a3cb3
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.PalmImagePlugin.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.PalmImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.PalmImagePlugin Module</h1>
+<h2>Module Contents</h2>
+<dl>
+<dt><a id='PIL.PalmImagePlugin._save-function' name='PIL.PalmImagePlugin._save-function'><b>_save(im, fp, filename, check=0)</b></a> [<a href='#PIL.PalmImagePlugin._save-function'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.PcdImagePlugin.html b/Imaging/Docs/pythondoc-PIL.PcdImagePlugin.html
new file mode 100644
index 0000000..feb6860
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.PcdImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.PcdImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.PcdImagePlugin Module</h1>
+<dl>
+<dt><b>PcdImageFile</b> (class) [<a href='#PIL.PcdImagePlugin.PcdImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for PhotoCD images.</p>
+<p>For more information about this class, see <a href='#PIL.PcdImagePlugin.PcdImageFile-class'><i>The PcdImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.PcdImagePlugin.PcdImageFile-class' name='PIL.PcdImagePlugin.PcdImageFile-class'>The PcdImageFile Class</a></h2>
+<dl>
+<dt><b>PcdImageFile</b> (class) [<a href='#PIL.PcdImagePlugin.PcdImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.PcfFontFile.html b/Imaging/Docs/pythondoc-PIL.PcfFontFile.html
new file mode 100644
index 0000000..8b1e41b
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.PcfFontFile.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.PcfFontFile Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.PcfFontFile Module</h1>
+<dl>
+<dt><b>PcfFontFile(fp)</b> (class) [<a href='#PIL.PcfFontFile.PcfFontFile-class'>#</a>]</dt>
+<dd>
+<p>Font file plugin for the X11 PCF format.</p>
+<p>For more information about this class, see <a href='#PIL.PcfFontFile.PcfFontFile-class'><i>The PcfFontFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.PcfFontFile.PcfFontFile-class' name='PIL.PcfFontFile.PcfFontFile-class'>The PcfFontFile Class</a></h2>
+<dl>
+<dt><b>PcfFontFile(fp)</b> (class) [<a href='#PIL.PcfFontFile.PcfFontFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.PcxImagePlugin.html b/Imaging/Docs/pythondoc-PIL.PcxImagePlugin.html
new file mode 100644
index 0000000..011349a
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.PcxImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.PcxImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.PcxImagePlugin Module</h1>
+<dl>
+<dt><b>PcxImageFile</b> (class) [<a href='#PIL.PcxImagePlugin.PcxImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for Paintbrush images.</p>
+<p>For more information about this class, see <a href='#PIL.PcxImagePlugin.PcxImageFile-class'><i>The PcxImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.PcxImagePlugin.PcxImageFile-class' name='PIL.PcxImagePlugin.PcxImageFile-class'>The PcxImageFile Class</a></h2>
+<dl>
+<dt><b>PcxImageFile</b> (class) [<a href='#PIL.PcxImagePlugin.PcxImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.PdfImagePlugin.html b/Imaging/Docs/pythondoc-PIL.PdfImagePlugin.html
new file mode 100644
index 0000000..20e0b3f
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.PdfImagePlugin.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.PdfImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.PdfImagePlugin Module</h1>
+<h2>Module Contents</h2>
+<dl>
+<dt><a id='PIL.PdfImagePlugin._save-function' name='PIL.PdfImagePlugin._save-function'><b>_save(im, fp, filename)</b></a> [<a href='#PIL.PdfImagePlugin._save-function'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.PixarImagePlugin.html b/Imaging/Docs/pythondoc-PIL.PixarImagePlugin.html
new file mode 100644
index 0000000..28b0614
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.PixarImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.PixarImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.PixarImagePlugin Module</h1>
+<dl>
+<dt><b>PixarImageFile</b> (class) [<a href='#PIL.PixarImagePlugin.PixarImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for PIXAR raster images.</p>
+<p>For more information about this class, see <a href='#PIL.PixarImagePlugin.PixarImageFile-class'><i>The PixarImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.PixarImagePlugin.PixarImageFile-class' name='PIL.PixarImagePlugin.PixarImageFile-class'>The PixarImageFile Class</a></h2>
+<dl>
+<dt><b>PixarImageFile</b> (class) [<a href='#PIL.PixarImagePlugin.PixarImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.PngImagePlugin.html b/Imaging/Docs/pythondoc-PIL.PngImagePlugin.html
new file mode 100644
index 0000000..ccd8e93
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.PngImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.PngImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.PngImagePlugin Module</h1>
+<dl>
+<dt><b>PngImageFile</b> (class) [<a href='#PIL.PngImagePlugin.PngImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for PNG images.</p>
+<p>For more information about this class, see <a href='#PIL.PngImagePlugin.PngImageFile-class'><i>The PngImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.PngImagePlugin.PngImageFile-class' name='PIL.PngImagePlugin.PngImageFile-class'>The PngImageFile Class</a></h2>
+<dl>
+<dt><b>PngImageFile</b> (class) [<a href='#PIL.PngImagePlugin.PngImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.PpmImagePlugin.html b/Imaging/Docs/pythondoc-PIL.PpmImagePlugin.html
new file mode 100644
index 0000000..2478968
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.PpmImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.PpmImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.PpmImagePlugin Module</h1>
+<dl>
+<dt><b>PpmImageFile</b> (class) [<a href='#PIL.PpmImagePlugin.PpmImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for PBM, PGM, and PPM images.</p>
+<p>For more information about this class, see <a href='#PIL.PpmImagePlugin.PpmImageFile-class'><i>The PpmImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.PpmImagePlugin.PpmImageFile-class' name='PIL.PpmImagePlugin.PpmImageFile-class'>The PpmImageFile Class</a></h2>
+<dl>
+<dt><b>PpmImageFile</b> (class) [<a href='#PIL.PpmImagePlugin.PpmImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.PsdImagePlugin.html b/Imaging/Docs/pythondoc-PIL.PsdImagePlugin.html
new file mode 100644
index 0000000..7ed4f80
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.PsdImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.PsdImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.PsdImagePlugin Module</h1>
+<dl>
+<dt><b>PsdImageFile</b> (class) [<a href='#PIL.PsdImagePlugin.PsdImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for Photoshop images.</p>
+<p>For more information about this class, see <a href='#PIL.PsdImagePlugin.PsdImageFile-class'><i>The PsdImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.PsdImagePlugin.PsdImageFile-class' name='PIL.PsdImagePlugin.PsdImageFile-class'>The PsdImageFile Class</a></h2>
+<dl>
+<dt><b>PsdImageFile</b> (class) [<a href='#PIL.PsdImagePlugin.PsdImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.SgiImagePlugin.html b/Imaging/Docs/pythondoc-PIL.SgiImagePlugin.html
new file mode 100644
index 0000000..847b35e
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.SgiImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.SgiImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.SgiImagePlugin Module</h1>
+<dl>
+<dt><b>SgiImageFile</b> (class) [<a href='#PIL.SgiImagePlugin.SgiImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for SGI images.</p>
+<p>For more information about this class, see <a href='#PIL.SgiImagePlugin.SgiImageFile-class'><i>The SgiImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.SgiImagePlugin.SgiImageFile-class' name='PIL.SgiImagePlugin.SgiImageFile-class'>The SgiImageFile Class</a></h2>
+<dl>
+<dt><b>SgiImageFile</b> (class) [<a href='#PIL.SgiImagePlugin.SgiImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.SpiderImagePlugin.html b/Imaging/Docs/pythondoc-PIL.SpiderImagePlugin.html
new file mode 100644
index 0000000..733f044
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.SpiderImagePlugin.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.SpiderImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.SpiderImagePlugin Module</h1>
+<p>Image plugin for the Spider image format. This format is is used
+by the SPIDER software, in processing image data from electron
+microscopy and tomography.</p>
+<h2>Module Contents</h2>
+<dl>
+<dt><b>SpiderImageFile</b> (class) [<a href='#PIL.SpiderImagePlugin.SpiderImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for the SPIDER format.</p>
+<p>For more information about this class, see <a href='#PIL.SpiderImagePlugin.SpiderImageFile-class'><i>The SpiderImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.SpiderImagePlugin.SpiderImageFile-class' name='PIL.SpiderImagePlugin.SpiderImageFile-class'>The SpiderImageFile Class</a></h2>
+<dl>
+<dt><b>SpiderImageFile</b> (class) [<a href='#PIL.SpiderImagePlugin.SpiderImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for the SPIDER format.</p>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.SunImagePlugin.html b/Imaging/Docs/pythondoc-PIL.SunImagePlugin.html
new file mode 100644
index 0000000..fb3cdd9
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.SunImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.SunImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.SunImagePlugin Module</h1>
+<dl>
+<dt><b>SunImageFile</b> (class) [<a href='#PIL.SunImagePlugin.SunImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for Sun raster files.</p>
+<p>For more information about this class, see <a href='#PIL.SunImagePlugin.SunImageFile-class'><i>The SunImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.SunImagePlugin.SunImageFile-class' name='PIL.SunImagePlugin.SunImageFile-class'>The SunImageFile Class</a></h2>
+<dl>
+<dt><b>SunImageFile</b> (class) [<a href='#PIL.SunImagePlugin.SunImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.TarIO.html b/Imaging/Docs/pythondoc-PIL.TarIO.html
new file mode 100644
index 0000000..996633b
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.TarIO.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.TarIO Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.TarIO Module</h1>
+<dl>
+<dt><b>TarIO(tarfile, file)</b> (class) [<a href='#PIL.TarIO.TarIO-class'>#</a>]</dt>
+<dd>
+<p>A file object that provides read access to a given member of a TAR
+file.</p>
+<p>For more information about this class, see <a href='#PIL.TarIO.TarIO-class'><i>The TarIO Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.TarIO.TarIO-class' name='PIL.TarIO.TarIO-class'>The TarIO Class</a></h2>
+<dl>
+<dt><b>TarIO(tarfile, file)</b> (class) [<a href='#PIL.TarIO.TarIO-class'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.TarIO.TarIO.__init__-method' name='PIL.TarIO.TarIO.__init__-method'><b>__init__(tarfile, file)</b></a> [<a href='#PIL.TarIO.TarIO.__init__-method'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>tarfile</i></dt>
+<dd>
+</dd>
+<dt><i>file</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.TgaImagePlugin.html b/Imaging/Docs/pythondoc-PIL.TgaImagePlugin.html
new file mode 100644
index 0000000..f91381e
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.TgaImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.TgaImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.TgaImagePlugin Module</h1>
+<dl>
+<dt><b>TgaImageFile</b> (class) [<a href='#PIL.TgaImagePlugin.TgaImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for Targa files.</p>
+<p>For more information about this class, see <a href='#PIL.TgaImagePlugin.TgaImageFile-class'><i>The TgaImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.TgaImagePlugin.TgaImageFile-class' name='PIL.TgaImagePlugin.TgaImageFile-class'>The TgaImageFile Class</a></h2>
+<dl>
+<dt><b>TgaImageFile</b> (class) [<a href='#PIL.TgaImagePlugin.TgaImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.TiffImagePlugin.html b/Imaging/Docs/pythondoc-PIL.TiffImagePlugin.html
new file mode 100644
index 0000000..56546d2
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.TiffImagePlugin.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.TiffImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.TiffImagePlugin Module</h1>
+<dl>
+<dt><b>ImageFileDirectory(prefix=&quot;II&quot;)</b> (class) [<a href='#PIL.TiffImagePlugin.ImageFileDirectory-class'>#</a>]</dt>
+<dd>
+<p>Wrapper for TIFF IFDs.</p>
+<p>For more information about this class, see <a href='#PIL.TiffImagePlugin.ImageFileDirectory-class'><i>The ImageFileDirectory Class</i></a>.</p>
+</dd>
+<dt><b>TiffImageFile</b> (class) [<a href='#PIL.TiffImagePlugin.TiffImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for TIFF files.</p>
+<p>For more information about this class, see <a href='#PIL.TiffImagePlugin.TiffImageFile-class'><i>The TiffImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.TiffImagePlugin.ImageFileDirectory-class' name='PIL.TiffImagePlugin.ImageFileDirectory-class'>The ImageFileDirectory Class</a></h2>
+<dl>
+<dt><b>ImageFileDirectory(prefix=&quot;II&quot;)</b> (class) [<a href='#PIL.TiffImagePlugin.ImageFileDirectory-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+<h2><a id='PIL.TiffImagePlugin.TiffImageFile-class' name='PIL.TiffImagePlugin.TiffImageFile-class'>The TiffImageFile Class</a></h2>
+<dl>
+<dt><b>TiffImageFile</b> (class) [<a href='#PIL.TiffImagePlugin.TiffImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.TiffTags.html b/Imaging/Docs/pythondoc-PIL.TiffTags.html
new file mode 100644
index 0000000..15d8c98
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.TiffTags.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.TiffTags Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.TiffTags Module</h1>
+<h2>Module Contents</h2>
+<dl>
+<dt><a id='PIL.TiffTags.TAGS-variable' name='PIL.TiffTags.TAGS-variable'><b>TAGS</b></a> (variable) [<a href='#PIL.TiffTags.TAGS-variable'>#</a>]</dt>
+<dd>
+</dd>
+<dt><a id='PIL.TiffTags.TYPES-variable' name='PIL.TiffTags.TYPES-variable'><b>TYPES</b></a> (variable) [<a href='#PIL.TiffTags.TYPES-variable'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.WalImageFile.html b/Imaging/Docs/pythondoc-PIL.WalImageFile.html
new file mode 100644
index 0000000..3b0b546
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.WalImageFile.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.WalImageFile Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.WalImageFile Module</h1>
+<dl>
+<dt><a id='PIL.WalImageFile.open-function' name='PIL.WalImageFile.open-function'><b>open(filename)</b></a> [<a href='#PIL.WalImageFile.open-function'>#</a>]</dt>
+<dd>
+<p>Load texture from a Quake2 WAL texture file.
+</p><p>
+By default, a Quake2 standard palette is attached to the texture.
+To override the palette, use the <b>putpalette</b> method.
+
+</p><dl>
+<dt><i>filename</i></dt>
+<dd>
+</dd>
+<dt>Returns:</dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.WmfImagePlugin.html b/Imaging/Docs/pythondoc-PIL.WmfImagePlugin.html
new file mode 100644
index 0000000..51bf103
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.WmfImagePlugin.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.WmfImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.WmfImagePlugin Module</h1>
+<dl>
+<dt><a id='PIL.WmfImagePlugin.register_handler-function' name='PIL.WmfImagePlugin.register_handler-function'><b>register_handler(handler)</b></a> [<a href='#PIL.WmfImagePlugin.register_handler-function'>#</a>]</dt>
+<dd>
+<dl>
+<dt><i>handler</i></dt>
+<dd>
+</dd>
+</dl><br />
+</dd>
+<dt><b>WmfStubImageFile</b> (class) [<a href='#PIL.WmfImagePlugin.WmfStubImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for Windows metafiles.</p>
+<p>For more information about this class, see <a href='#PIL.WmfImagePlugin.WmfStubImageFile-class'><i>The WmfStubImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.WmfImagePlugin.WmfStubImageFile-class' name='PIL.WmfImagePlugin.WmfStubImageFile-class'>The WmfStubImageFile Class</a></h2>
+<dl>
+<dt><b>WmfStubImageFile</b> (class) [<a href='#PIL.WmfImagePlugin.WmfStubImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.XVThumbImagePlugin.html b/Imaging/Docs/pythondoc-PIL.XVThumbImagePlugin.html
new file mode 100644
index 0000000..30282ac
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.XVThumbImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.XVThumbImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.XVThumbImagePlugin Module</h1>
+<dl>
+<dt><b>XVThumbImageFile</b> (class) [<a href='#PIL.XVThumbImagePlugin.XVThumbImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for XV thumbnail images.</p>
+<p>For more information about this class, see <a href='#PIL.XVThumbImagePlugin.XVThumbImageFile-class'><i>The XVThumbImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.XVThumbImagePlugin.XVThumbImageFile-class' name='PIL.XVThumbImagePlugin.XVThumbImageFile-class'>The XVThumbImageFile Class</a></h2>
+<dl>
+<dt><b>XVThumbImageFile</b> (class) [<a href='#PIL.XVThumbImagePlugin.XVThumbImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.XbmImagePlugin.html b/Imaging/Docs/pythondoc-PIL.XbmImagePlugin.html
new file mode 100644
index 0000000..682e05f
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.XbmImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.XbmImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.XbmImagePlugin Module</h1>
+<dl>
+<dt><b>XbmImageFile</b> (class) [<a href='#PIL.XbmImagePlugin.XbmImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for X11 bitmaps.</p>
+<p>For more information about this class, see <a href='#PIL.XbmImagePlugin.XbmImageFile-class'><i>The XbmImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.XbmImagePlugin.XbmImageFile-class' name='PIL.XbmImagePlugin.XbmImageFile-class'>The XbmImageFile Class</a></h2>
+<dl>
+<dt><b>XbmImageFile</b> (class) [<a href='#PIL.XbmImagePlugin.XbmImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Docs/pythondoc-PIL.XpmImagePlugin.html b/Imaging/Docs/pythondoc-PIL.XpmImagePlugin.html
new file mode 100644
index 0000000..218f704
--- /dev/null
+++ b/Imaging/Docs/pythondoc-PIL.XpmImagePlugin.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
+<title>The PIL.XpmImagePlugin Module</title>
+<link rel='stylesheet' href='effbot.css' type='text/css' />
+</head>
+<body>
+<h1>The PIL.XpmImagePlugin Module</h1>
+<dl>
+<dt><b>XpmImageFile</b> (class) [<a href='#PIL.XpmImagePlugin.XpmImageFile-class'>#</a>]</dt>
+<dd>
+<p>Image plugin for X11 pixel maps.</p>
+<p>For more information about this class, see <a href='#PIL.XpmImagePlugin.XpmImageFile-class'><i>The XpmImageFile Class</i></a>.</p>
+</dd>
+</dl>
+<h2><a id='PIL.XpmImagePlugin.XpmImageFile-class' name='PIL.XpmImagePlugin.XpmImageFile-class'>The XpmImageFile Class</a></h2>
+<dl>
+<dt><b>XpmImageFile</b> (class) [<a href='#PIL.XpmImagePlugin.XpmImageFile-class'>#</a>]</dt>
+<dd>
+</dd>
+</dl>
+</body></html>
diff --git a/Imaging/Images/courB08.bdf b/Imaging/Images/courB08.bdf
new file mode 100644
index 0000000..5a48895
--- /dev/null
+++ b/Imaging/Images/courB08.bdf
@@ -0,0 +1,2676 @@
+STARTFONT 2.1
+COMMENT $XConsortium: courB08.bdf,v 1.5 94/04/10 21:46:11 gildea Exp $
+COMMENT
+COMMENT Copyright 1984, 1987 Adobe Systems, Inc.
+COMMENT Portions Copyright 1988 Digital Equipment Corporation
+COMMENT
+COMMENT Adobe is a registered trademark of Adobe Systems, Inc. Permission
+COMMENT to use these trademarks is hereby granted only in association with the
+COMMENT images described in this file.
+COMMENT
+COMMENT Permission to use, copy, modify, and distribute this software and
+COMMENT its documentation for any purpose and without fee is hereby granted,
+COMMENT provided that the above copyright notices appear in all copies and
+COMMENT that both those copyright notices and this permission notice appear
+COMMENT in supporting documentation, and that the names of Adobe Systems and
+COMMENT Digital Equipment Corporation not be used in advertising or
+COMMENT publicity pertaining to distribution of the software without
+COMMENT specific, written prior permission. Adobe Systems and Digital
+COMMENT Equipment Corporation make no representations about the suitability
+COMMENT of this software for any purpose. It is provided "as is" without
+COMMENT express or implied warranty.
+COMMENT
+COMMENT ADOBE SYSTEMS AND DIGITAL EQUIPMENT CORPORATION DISCLAIM ALL
+COMMENT WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
+COMMENT WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ADOBE
+COMMENT SYSTEMS AND DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY SPECIAL,
+COMMENT INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+COMMENT RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+COMMENT CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+COMMENT CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+COMMENT
+COMMENT
+FONT -Adobe-Courier-Bold-R-Normal--11-80-100-100-M-60-ISO8859-1
+SIZE 8 100 100
+FONTBOUNDINGBOX 8 11 -1 -2
+STARTPROPERTIES 22
+COMMENT Begin LogicalFontDescription
+FONTNAME_REGISTRY ""
+FAMILY_NAME "Courier"
+FOUNDRY "Adobe"
+WEIGHT_NAME "Bold"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 11
+POINT_SIZE 80
+RESOLUTION_X 100
+RESOLUTION_Y 100
+SPACING "M"
+AVERAGE_WIDTH 60
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+COMMENT END LogicalFontDescription
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FACE_NAME "Courier Bold"
+COPYRIGHT "Copyright (c) 1987 Adobe Systems, Inc., Portions Copyright 1988 Digital Equipment Corp."
+COMMENT ***** end of inserted font properties
+FONT_ASCENT 8
+FONT_DESCENT 2
+CAP_HEIGHT 6
+X_HEIGHT 5
+ENDPROPERTIES
+CHARS 194
+STARTCHAR space
+ENCODING 32
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 2 6 1 0
+BITMAP
+C0
+C0
+C0
+C0
+00
+C0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 3 3 1 3
+BITMAP
+A0
+A0
+A0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 8 0 -1
+BITMAP
+50
+50
+F8
+50
+50
+F8
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 9 0 -1
+BITMAP
+20
+78
+C8
+F0
+78
+18
+D8
+F0
+20
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+E0
+A8
+F0
+20
+78
+A8
+38
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 6 -1 0
+BITMAP
+38
+60
+30
+7C
+D8
+7C
+ENDCHAR
+STARTCHAR quoteright
+ENCODING 39
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 3 3 1 4
+BITMAP
+60
+40
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 3 8 1 -1
+BITMAP
+20
+40
+C0
+C0
+C0
+C0
+40
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 3 8 1 -1
+BITMAP
+80
+40
+60
+60
+60
+60
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 4 4 0 3
+BITMAP
+20
+F0
+60
+90
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 5 0 1
+BITMAP
+20
+20
+F8
+20
+20
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 3 3 1 -2
+BITMAP
+60
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 1 0 3
+BITMAP
+F8
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 2 1 1 0
+BITMAP
+C0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 4 8 1 -1
+BITMAP
+10
+10
+20
+20
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR zero
+ENCODING 48
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+70
+D8
+D8
+D8
+D8
+D8
+70
+ENDCHAR
+STARTCHAR one
+ENCODING 49
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+30
+F0
+30
+30
+30
+30
+FC
+ENDCHAR
+STARTCHAR two
+ENCODING 50
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+70
+D8
+18
+30
+60
+D8
+F8
+ENDCHAR
+STARTCHAR three
+ENCODING 51
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+70
+D8
+18
+70
+18
+D8
+70
+ENDCHAR
+STARTCHAR four
+ENCODING 52
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+18
+38
+58
+D8
+FC
+18
+18
+ENDCHAR
+STARTCHAR five
+ENCODING 53
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+F8
+C0
+F0
+D8
+18
+98
+F0
+ENDCHAR
+STARTCHAR six
+ENCODING 54
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+70
+D8
+C0
+F0
+D8
+D8
+70
+ENDCHAR
+STARTCHAR seven
+ENCODING 55
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+F8
+D8
+18
+30
+30
+60
+60
+ENDCHAR
+STARTCHAR eight
+ENCODING 56
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+70
+D8
+D8
+70
+D8
+D8
+70
+ENDCHAR
+STARTCHAR nine
+ENCODING 57
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+70
+D8
+D8
+78
+18
+D8
+70
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 2 4 1 0
+BITMAP
+C0
+00
+00
+C0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 3 6 0 -2
+BITMAP
+60
+00
+00
+60
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 4 5 0 1
+BITMAP
+30
+60
+C0
+60
+30
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 4 3 0 2
+BITMAP
+F0
+00
+F0
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 4 5 1 1
+BITMAP
+C0
+60
+30
+60
+C0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+70
+98
+30
+60
+00
+60
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 8 0 -1
+BITMAP
+70
+C8
+98
+A8
+A8
+9C
+C0
+70
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 6 -1 0
+BITMAP
+78
+38
+28
+7C
+6C
+EE
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 6 -1 0
+BITMAP
+F8
+6C
+78
+6C
+6C
+F8
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+78
+D8
+C0
+C0
+D8
+70
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 6 -1 0
+BITMAP
+F8
+6C
+6C
+6C
+6C
+F8
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 6 -1 0
+BITMAP
+FC
+60
+78
+60
+6C
+FC
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 6 -1 0
+BITMAP
+FC
+60
+78
+60
+60
+F0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+70
+D8
+C0
+F8
+D8
+78
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 6 -1 0
+BITMAP
+EE
+6C
+7C
+6C
+6C
+EE
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 4 6 0 0
+BITMAP
+F0
+60
+60
+60
+60
+F0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 6 -1 0
+BITMAP
+3C
+18
+18
+D8
+D8
+70
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 6 -1 0
+BITMAP
+EC
+68
+70
+78
+6C
+F6
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 6 -1 0
+BITMAP
+F0
+60
+60
+60
+6C
+FC
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 6 -1 0
+BITMAP
+C4
+6C
+6C
+7C
+54
+D4
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 6 -1 0
+BITMAP
+EE
+74
+74
+6C
+6C
+E4
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+70
+D8
+D8
+D8
+D8
+70
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 6 -1 0
+BITMAP
+F8
+6C
+6C
+78
+60
+F0
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 7 0 -1
+BITMAP
+70
+D8
+D8
+D8
+D8
+70
+18
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 6 -1 0
+BITMAP
+F8
+6C
+6C
+78
+6C
+F6
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+78
+C8
+F0
+38
+98
+F0
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 6 -1 0
+BITMAP
+FC
+B4
+30
+30
+30
+78
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 6 -1 0
+BITMAP
+EE
+6C
+6C
+6C
+6C
+38
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 6 -1 0
+BITMAP
+EE
+6C
+28
+38
+38
+10
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 6 -1 0
+BITMAP
+D6
+54
+54
+7C
+38
+28
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 6 0 0
+BITMAP
+CC
+78
+30
+30
+78
+CC
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 6 -1 0
+BITMAP
+E6
+66
+3C
+18
+18
+3C
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+F8
+D8
+30
+60
+D8
+F8
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 3 8 1 -1
+BITMAP
+E0
+C0
+C0
+C0
+C0
+C0
+C0
+E0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 4 8 0 -1
+BITMAP
+80
+80
+40
+40
+20
+20
+10
+10
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 3 8 1 -1
+BITMAP
+E0
+60
+60
+60
+60
+60
+60
+E0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 3 0 4
+BITMAP
+20
+70
+D8
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 1 0 -2
+BITMAP
+FC
+ENDCHAR
+STARTCHAR quoteleft
+ENCODING 96
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 3 3 1 4
+BITMAP
+C0
+40
+20
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 5 0 0
+BITMAP
+70
+D8
+78
+D8
+FC
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 7 -1 0
+BITMAP
+E0
+60
+78
+6C
+6C
+6C
+F8
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+70
+D8
+C0
+D8
+70
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+38
+18
+78
+D8
+D8
+D8
+7C
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+70
+D8
+F8
+C0
+78
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+38
+60
+F8
+60
+60
+60
+F8
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 7 0 -2
+BITMAP
+6C
+D8
+D8
+D8
+78
+18
+F0
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 7 -1 0
+BITMAP
+E0
+60
+78
+6C
+6C
+6C
+6C
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+30
+00
+F0
+30
+30
+30
+FC
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 4 9 0 -2
+BITMAP
+30
+00
+F0
+30
+30
+30
+30
+30
+E0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 7 -1 0
+BITMAP
+E0
+60
+6C
+78
+70
+78
+6E
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+F0
+30
+30
+30
+30
+30
+FC
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 5 -1 0
+BITMAP
+F8
+7C
+54
+54
+54
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 5 -1 0
+BITMAP
+D8
+6C
+6C
+6C
+6C
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+70
+D8
+D8
+D8
+70
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 7 -1 -2
+BITMAP
+F8
+6C
+6C
+6C
+78
+60
+F0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 7 0 -2
+BITMAP
+6C
+D8
+D8
+D8
+78
+18
+3C
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 5 0 0
+BITMAP
+DC
+74
+60
+60
+F0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 5 0 0
+BITMAP
+78
+E0
+78
+1C
+F8
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+60
+60
+F8
+60
+60
+6C
+38
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 5 -1 0
+BITMAP
+EC
+6C
+6C
+6C
+3E
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 5 -1 0
+BITMAP
+EC
+6C
+38
+38
+10
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 5 -1 0
+BITMAP
+D6
+54
+7C
+3C
+28
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 5 0 0
+BITMAP
+EC
+78
+30
+78
+DC
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 7 -1 -2
+BITMAP
+EE
+6C
+6C
+28
+38
+30
+E0
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+F8
+B0
+60
+D8
+F8
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 4 8 1 -1
+BITMAP
+30
+60
+60
+C0
+60
+60
+60
+30
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 1 7 2 -1
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 4 8 0 -1
+BITMAP
+C0
+60
+60
+30
+60
+60
+60
+C0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 2 0 3
+BITMAP
+68
+B0
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 2 7 1 -2
+BITMAP
+C0
+00
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 8 0 -1
+BITMAP
+20
+20
+78
+C8
+C0
+78
+20
+20
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+38
+68
+20
+F8
+20
+64
+F8
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 5 0 1
+BITMAP
+88
+70
+50
+70
+88
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+CC
+48
+FC
+30
+FC
+30
+78
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 1 9 2 -2
+BITMAP
+80
+80
+80
+80
+00
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 8 0 -1
+BITMAP
+78
+48
+60
+90
+48
+30
+90
+F0
+ENDCHAR
+STARTCHAR dieresis
+ENCODING 168
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 3 1 1 5
+BITMAP
+A0
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+30
+48
+B4
+A4
+B4
+48
+30
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 4 5 1 2
+BITMAP
+E0
+10
+D0
+00
+F0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 5 -1 0
+BITMAP
+36
+6C
+D8
+6C
+36
+ENDCHAR
+STARTCHAR logicalnot
+ENCODING 172
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 3 0 2
+BITMAP
+F8
+08
+08
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 1 0 3
+BITMAP
+F8
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 7 0 0
+BITMAP
+38
+44
+BA
+B2
+AA
+44
+38
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 4 1 0 5
+BITMAP
+F0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 4 3 0 4
+BITMAP
+60
+90
+60
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+20
+20
+F8
+20
+00
+F8
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 3 4 1 3
+BITMAP
+60
+A0
+40
+E0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 3 4 1 3
+BITMAP
+E0
+40
+20
+C0
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 2 2 2 5
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 7 -1 -2
+BITMAP
+EC
+6C
+6C
+6C
+7E
+40
+40
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 8 0 -1
+BITMAP
+7C
+A8
+A8
+68
+28
+28
+28
+6C
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 2 1 1 3
+BITMAP
+C0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 3 3 1 -2
+BITMAP
+40
+20
+C0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 3 4 1 3
+BITMAP
+C0
+40
+40
+E0
+ENDCHAR
+STARTCHAR ordmasculine
+ENCODING 186
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 4 5 1 2
+BITMAP
+60
+90
+60
+00
+F0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 5 -1 0
+BITMAP
+D8
+6C
+36
+6C
+D8
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 7 -1 0
+BITMAP
+C0
+44
+48
+F4
+2C
+5E
+04
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 7 -1 0
+BITMAP
+C0
+44
+48
+F6
+2A
+44
+0E
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 7 -1 0
+BITMAP
+E0
+44
+28
+D4
+2C
+5E
+04
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 7 0 -2
+BITMAP
+30
+00
+30
+30
+60
+C8
+70
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 9 -1 0
+BITMAP
+20
+10
+00
+78
+38
+28
+7C
+6C
+EE
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 9 -1 0
+BITMAP
+10
+20
+00
+78
+38
+28
+7C
+6C
+EE
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 9 -1 0
+BITMAP
+10
+28
+00
+78
+38
+28
+7C
+6C
+EE
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 9 -1 0
+BITMAP
+34
+48
+00
+78
+38
+28
+7C
+6C
+EE
+ENDCHAR
+STARTCHAR Adieresis
+ENCODING 196
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 8 -1 0
+BITMAP
+28
+00
+78
+38
+28
+7C
+6C
+EE
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 9 -1 0
+BITMAP
+30
+48
+30
+78
+38
+28
+7C
+6C
+EE
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 6 -1 0
+BITMAP
+7E
+3A
+6C
+78
+DA
+DE
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 8 0 -2
+BITMAP
+78
+D8
+C0
+C0
+D8
+70
+10
+60
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 9 -1 0
+BITMAP
+20
+10
+00
+FC
+64
+78
+60
+6C
+FC
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 9 -1 0
+BITMAP
+10
+20
+00
+FC
+64
+78
+60
+6C
+FC
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 9 -1 0
+BITMAP
+20
+50
+00
+FC
+64
+78
+60
+6C
+FC
+ENDCHAR
+STARTCHAR Edieresis
+ENCODING 203
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 8 -1 0
+BITMAP
+50
+00
+FC
+64
+78
+60
+6C
+FC
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 4 9 0 0
+BITMAP
+40
+20
+00
+F0
+60
+60
+60
+60
+F0
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 4 9 0 0
+BITMAP
+20
+40
+00
+F0
+60
+60
+60
+60
+F0
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 4 9 0 0
+BITMAP
+40
+A0
+00
+F0
+60
+60
+60
+60
+F0
+ENDCHAR
+STARTCHAR Idieresis
+ENCODING 207
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 4 8 0 0
+BITMAP
+A0
+00
+F0
+60
+60
+60
+60
+F0
+ENDCHAR
+STARTCHAR Eth
+ENCODING 208
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 6 -1 0
+BITMAP
+F8
+6C
+F4
+64
+6C
+F8
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 9 -1 0
+BITMAP
+34
+48
+00
+EE
+64
+74
+7C
+6C
+EC
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+40
+20
+00
+70
+D8
+D8
+D8
+D8
+70
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+20
+40
+00
+70
+D8
+D8
+D8
+D8
+70
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+20
+50
+00
+70
+D8
+D8
+D8
+D8
+70
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+68
+90
+00
+70
+D8
+D8
+D8
+D8
+70
+ENDCHAR
+STARTCHAR Odieresis
+ENCODING 214
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+50
+00
+70
+D8
+D8
+D8
+D8
+70
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 5 0 1
+BITMAP
+88
+50
+20
+50
+88
+ENDCHAR
+STARTCHAR Oslash
+ENCODING 216
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 6 -1 0
+BITMAP
+3A
+6C
+7C
+6C
+6C
+B8
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 9 -1 0
+BITMAP
+20
+10
+00
+EE
+6C
+6C
+6C
+6C
+38
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 9 -1 0
+BITMAP
+08
+10
+00
+EE
+6C
+6C
+6C
+6C
+38
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 9 -1 0
+BITMAP
+10
+28
+00
+EE
+6C
+6C
+6C
+6C
+38
+ENDCHAR
+STARTCHAR Udieresis
+ENCODING 220
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 8 -1 0
+BITMAP
+28
+00
+EE
+6C
+6C
+6C
+6C
+38
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 9 -1 0
+BITMAP
+04
+08
+00
+E6
+66
+3C
+18
+18
+3C
+ENDCHAR
+STARTCHAR Thorn
+ENCODING 222
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 6 -1 0
+BITMAP
+E0
+78
+6C
+6C
+78
+E0
+ENDCHAR
+STARTCHAR germandbls
+ENCODING 223
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 6 -1 0
+BITMAP
+38
+68
+7C
+66
+66
+EC
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 8 0 0
+BITMAP
+20
+10
+00
+70
+98
+78
+D8
+FC
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 8 0 0
+BITMAP
+10
+20
+00
+70
+98
+78
+D8
+FC
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 8 0 0
+BITMAP
+20
+50
+00
+70
+98
+78
+D8
+FC
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 8 0 0
+BITMAP
+68
+90
+00
+70
+98
+78
+D8
+FC
+ENDCHAR
+STARTCHAR adieresis
+ENCODING 228
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+50
+00
+70
+98
+78
+D8
+FC
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+30
+48
+30
+00
+70
+98
+78
+D8
+FC
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 5 -1 0
+BITMAP
+6C
+B4
+7C
+B0
+DC
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 7 0 -2
+BITMAP
+70
+D8
+C0
+D8
+70
+10
+60
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+40
+20
+00
+70
+D8
+F8
+C0
+78
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+20
+40
+00
+70
+D8
+F8
+C0
+78
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+20
+50
+00
+70
+D8
+F8
+C0
+78
+ENDCHAR
+STARTCHAR edieresis
+ENCODING 235
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+50
+00
+70
+D8
+F8
+C0
+78
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 8 0 0
+BITMAP
+20
+10
+00
+70
+30
+30
+30
+FC
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 8 0 0
+BITMAP
+10
+20
+00
+70
+30
+30
+30
+FC
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 8 0 0
+BITMAP
+20
+50
+00
+70
+30
+30
+30
+FC
+ENDCHAR
+STARTCHAR idieresis
+ENCODING 239
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+50
+00
+70
+30
+30
+30
+FC
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+D0
+60
+B0
+78
+D8
+D8
+D8
+70
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 8 -1 0
+BITMAP
+34
+48
+00
+D8
+6C
+6C
+6C
+6E
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+40
+20
+00
+70
+D8
+D8
+D8
+70
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+20
+40
+00
+70
+D8
+D8
+D8
+70
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+20
+50
+00
+70
+D8
+D8
+D8
+70
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+68
+90
+00
+70
+D8
+D8
+D8
+70
+ENDCHAR
+STARTCHAR odieresis
+ENCODING 246
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+50
+00
+70
+D8
+D8
+D8
+70
+ENDCHAR
+STARTCHAR divide
+ENCODING 247
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 5 0 1
+BITMAP
+20
+00
+F8
+00
+20
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 5 7 0 -1
+BITMAP
+08
+70
+D8
+F8
+D8
+70
+80
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 8 -1 0
+BITMAP
+20
+10
+00
+EC
+6C
+6C
+6C
+3E
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 8 -1 0
+BITMAP
+10
+20
+00
+EC
+6C
+6C
+6C
+3E
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 8 -1 0
+BITMAP
+10
+28
+00
+EC
+6C
+6C
+6C
+3E
+ENDCHAR
+STARTCHAR udieresis
+ENCODING 252
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 7 -1 0
+BITMAP
+28
+00
+EC
+6C
+6C
+6C
+3E
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 10 -1 -2
+BITMAP
+08
+10
+00
+EE
+6C
+6C
+28
+38
+30
+F0
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 9 -1 -2
+BITMAP
+E0
+60
+78
+6C
+6C
+6C
+78
+60
+F0
+ENDCHAR
+STARTCHAR ydieresis
+ENCODING 255
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 9 -1 -2
+BITMAP
+28
+00
+EE
+6C
+6C
+28
+38
+30
+F0
+ENDCHAR
+STARTCHAR trademark
+ENCODING 8482
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 4 -1 3
+BITMAP
+F6
+5E
+5A
+5A
+ENDCHAR
+STARTCHAR perthousand
+ENCODING 8240
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+60
+A8
+D0
+60
+6C
+B4
+D8
+ENDCHAR
+STARTCHAR oe
+ENCODING 339
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 6 5 0 0
+BITMAP
+6C
+B4
+BC
+B0
+6C
+ENDCHAR
+STARTCHAR fl
+ENCODING 64258
+SWIDTH 600 0
+DWIDTH 6 0
+BBX 7 7 -1 0
+BITMAP
+3C
+6C
+FC
+6C
+6C
+6C
+FE
+ENDCHAR
+ENDFONT
diff --git a/Imaging/Images/courB08.pbm b/Imaging/Images/courB08.pbm
new file mode 100644
index 0000000..aedce1a
--- /dev/null
+++ b/Imaging/Images/courB08.pbm
Binary files differ
diff --git a/Imaging/Images/courB08.pil b/Imaging/Images/courB08.pil
new file mode 100644
index 0000000..28982c0
--- /dev/null
+++ b/Imaging/Images/courB08.pil
Binary files differ
diff --git a/Imaging/Images/lena.gif b/Imaging/Images/lena.gif
new file mode 100644
index 0000000..64a9b93
--- /dev/null
+++ b/Imaging/Images/lena.gif
Binary files differ
diff --git a/Imaging/Images/lena.jpg b/Imaging/Images/lena.jpg
new file mode 100644
index 0000000..ed01c4e
--- /dev/null
+++ b/Imaging/Images/lena.jpg
Binary files differ
diff --git a/Imaging/Images/lena.ppm b/Imaging/Images/lena.ppm
new file mode 100644
index 0000000..06a398e
--- /dev/null
+++ b/Imaging/Images/lena.ppm
@@ -0,0 +1,4 @@
+P6
+128 128
+255
+ߢ…ä£{ä¡~ߟxÞ¡yàšfß›lÜšyâ›jåŸhæ¦ué­yê§vé¡pÛš»ubž^Y¦f]©g[¯gZ±kX­m\±kY²jT²m]³iQ¶u\Ây\ÃxZÀyaÎ_Ê„`чeÊ‚fÌ„eË€_ËaÌ]Ì€]·nÒ‚]φeÖ‚[Ð…d̆iÌ‚aΈeÌ…cЄ_Ó…\Ì…nË„fσcÊ[΃^Í[ɇjÉ‚dЃ\у^Є_φc΄aÍ…gφbÈ€\Ê€_Ѓ]΃`ЇbÇ~[Ë…i΃eʃaÉ}^È~ZÁ|i¾yb²p[ªfR½tbЇ_Ö‘mÞ™mߣuÝ›hÜ™hß—iÚšyÝšqàšhÞ–dÞ™kݘeß—iݘbÝšjÞšjÝŸqÝœoàžlôΑøÕýÙž÷ҕϘt¥dV¬h[¹w]¸y^ÀwV¿yWº|d¼{iÀ{_¾yaÅfÂ|c¿{c½uXÂ~dÀ{[ÄdÀwZ¼sX¹xfå§Ý›nãqâžxãšjáœkß™kâ˜làšiÞ›eܘnç¡néªzî¯|í«~ëžcÜm¹n]Ÿ\T¤`W¦b\­jY±kT°gV¯jV°iT¶nV²oZ·mTÂvYÁvWÆzbÉ~_È}]˃gÊ_Èãb΀`Ì‚a΂`χkцhÓ‰gÕ„`ΈlÒ‰`ÎbÒƒ]Ó…^Í…a΃j͇f̓m͆gÊ`΀ZÏ]È~]É`È_Ì€\΃]φdÒ[͆gφhÍ„a̓^Ìb̃bÈ…lÈ|Zʃf̃gÉ~dÉ_Å}`¿y\¼w\¹vaªiY³mUË€WÖjÝ™uÞŸkÞŸoà˜fÚšvÝ›rÚ—kÞœqàšgÞ—há˜dá–_Ü›bà˜fÜ›gÞ›mÝšiÚuóȃúÖ˜ýÚ ùןۣv£aQ¬pf´sZ¼w\ÁyVÂzV½{eµv`ÁwVÃ{^Ã}]¿xZ¿{]½vXÂx\Ç_Åe¿y[¾rS¾}dØ•t¬gQàmà›lá›wàpß™iâ›dà˜kà›lâšcå¤uìªtë¨nï©tå›`׋^¼qYž[P£YO®dM°eO´iQ³iV°kR°gM±fM±hX°iS·t]È|^Ã~_Æ}aÉ}\Ê€fÕƒXËXʈi΀[Í[Ì[΂_΄_Ó†`Ö‡\Õ…^Ñ…fÏ„_шiÍ„`ÓƒbÌ„lЃ`Ë}^Ô†aʃiÍ‚bÌ€^ΆbÍ‚dÍ|YɃbÐ\Ñ„^Í€[Í`ЈgЄaÉ]È‚iË‚dÍ\Å~eÉzZË‚ZÉ}[ÆvYÄ}^Ã|b¾wc¶q[¯gR«eT¾v[Ò‹lÙ•oÜzÞ sÝžwÙšmàœeÞœrà™kà™dãœdÞšlàœoß™fßnÚ™iÙ™qܘfÙ›sç³|öÒ˜ûؘüÙšó̇¹z_«hSµoXºtX¾uX¸za¹w\¿zY¼zhÄzYÄ{Z¿{[Ä}cÇcÅ}\È}\Ã}\ʃdÅ~_±iOa5?\-=áoåœiâšiâ™dßžxâ–eà˜hãœgæžmå¦qæ§mì§hë¦cãžkÓ‰c´mQžVI¢\KªcR±jT´o^²mQ°fN³kO²fP´iSÀnOÂwWÅtSÄvYÈzYË\ÏzQÏ‚e΃eцhÓ„_Ò…iË€_φdÑ]ÎXÒ…bÓ„[Õ„ZÏ]Ђ`Ó†bÏ^χkÒ‚^͇kÒ‚`Ï…cÏ„iÑ€\ÎaÑ]ЀVÑ€XÔ†aÓ…fÏ]ЂaÍ„cЃbÏ€_Ç`ΆdËa˃bÌYÅ}aËbÌ\Ç|`Ç|bÄ|c¸p\³p\±kV«j[Í„d×nߘná¡ißžoàkãjà¡næ¡kåŸoâšháœgß›mà•`â™^Û—bÝšmÙ˜oÙ—kØ–kñĉøÕ›üÚœûØšã³~¤gX°s^½sT¹rZº{fÂvWÀxZ¾x]½vU¾yZÂ{ZÃ|\ÄyUÊbÈ‚^Ê}_Ó„^³mT_;PW(;[0Aá›oá–eãžkâ›mâ™]äœhÝšpá£}æ¦yå¥ké¦tê¤nè kâ˜i؇Z»lP \P¢^L«hW®dN´eHµkR¶kQ´n]²eJ¸gKÂpMÂpNÅuTÆybÉ}XÎ}XÐ\È„gÓW΃^Ò„`Òƒ]Ñ…a΂^ÏZÏ…dÒ„XÕ„]Ò†lÓ~VÕ„_Ï…bÔ‚^̃]Í‚[ІjІeЄbÏ`Ì„^σ\΂aÌ~UÔ‚XÒŠmÓ‰fЂ\σ]Ò[Óƒ^̓aÊ‚_Ñ‚]Î^Ì}_Ï|[Ï…iÎaÎaÈ€`¿}fÅz[ºqU±wg»s\«hY¾yf×—zÝ–nÞšmߣuá£zåžjå£rá såŸmã¡xáœgâžlâ›mßœfÝ•f×—tÙ—oÛ–kÖ”käªtøÏúØœüÚžøÑ•ÍŽa³oW³nU»t]·yd»{bÆ}^Á}]Ã`À}bÅa»gË}YÊaу`̓c§_N[,;U-?V.<\-;â›jâœjæ›eå›dážtã™eߘkߢwé¨oç£pç¤uå¡næ¡hå¡u؉Y¸oS¤bPŸ\N­eR³fL¸iT³iJ°nU°fN®cH²hP¸oTÃtQÀuUÆ}]Í}SÁ{d΃dÌ^ÏV΂d΃bÐ`ʃeÌ„cÐaÏUÑYÖ‡aÓ„ZÓƒ]Î}YÕƒZÍ\Ò…aЃ]Óƒ^Î`΂`у_Ç~^΂`Í\Î[Ì\Ò„bÒ‰hуdσaÑWÎ`Ë~WЃe΀`Ë}YÇ€gË~]Êz\΃cÐZË~YÂz^Á{dÃy^·q[³mW°jW°o\ЋiÚ“eÞ›nã¢yå¦väiä¡rã¢kæ¢iã lá›mâšoâ›qÝ uÞ™qܘgÚ˜pØ”pÙ–nÚdï½|úÔ˜ûÚüÚšòÄ‚¨hS¬jV²q[»tZÂz^Á~`ºs^½|c¸|iÀ†sȃiÉ‚dÓ‡cÕf¤_O[->W):V1EW/>e7EÞ˜käqã¢râœdâœpãœoæŸmæ§|é¤uæ§wå£pâhå¢pä—]Ý‹Y¿r[¢XF¦[L­`L¯hO²gO·hP²mU°gR±iQ¹mP¶oW½sRÃ{WÈxTÇxTÇ~^Ð[Ê[ÐWÏ]ÏZÓ„]Ë…nÑ~\ÔZÒVÒƒ]ØVÓƒ^Ô~VÐ[Ï‚aÒ†eÒ‚[Ö^Ñ}VÍyUÍ~WÌcÏ~YÓXÊ|\ÍZÈ|[Ì~^Ï…gÕ€YЂ^σ_΂aÐ\Ð}XЀ[ЂbÊ}ZÍ€cÐbÐ~WÍ}YÌ`Ç{ZÆ{b¿yb³nZ³lS®h\´wlψnÙ“qàžuá¡wä¡zä¦zà ~âŸnâŸdäŸhߘgÞjäšcá›oÞšpÛ›mÞ˜fÛ–iÙ—oÖ“kÞm÷ËùÙ¢ûÝŸüÖ•×¥j©dM®kX¼vW¾y[Å|T¼x`ÁzZ»t]ÀkÃ}_Ò€`Ô‹g¥^RgIYW'7X/DZ-8a1:f6=æžhåfãŸzæŸkâjâŸvæ£måªrè¥mä¥wä¡iájå¡oç`Ù_¾pMžYM¦\J­`L³jQ¸lQ³iM´eI¯eM¯fP¸jPµgNÀrQÆwPÅxTÆ{\Ç]ÌYÌyRÍ‚]ÎZЃYÌaÈ€gÌ‚dσaÓYÑ‚ZцfÖ†cÑ}XÒ{UÓ‚aуcÐ…lÊ{VÎ}TÊxSË|\Ê{^Ï^Ë}_Î|\Í|WÌ|XÑ€^Ì^Ô]Í`Ï]чeÈz]É€Z΄bÏ\Ð}YÌ}]ÌWÐ}\Í^Ð…`É}]Ãw`Æ{bºnW·pZ³lZ·sbσh×”yÝœ|àžwã£{âŸyàžsÞŸráœrã¡nâ¡fá›gàšnâškßvÛœvÚ˜lÚ•c×”fÙ‘lÖ”kñºyùÕ˜ùÙŸýÞ¤ôËŒ³nN¯kT¾uT¾uU¾z\»xdÅxV¹x]Æ|`ȃ`ÑŠgŸYIT/DW-D^3D\*7e5Bj5A^2<äŸpã rå›iã£væ¤zç¥xëªqèªuä©tæ aâ páfæ aæœd݉U¿oS¡]N¨_V«aI°dNµhO°hR´dJ³fM°fN¶jS»pVÃrQÇvVÁx]¾wXÇ|bÎZÍ{ZÉ|[Ì}YÍ~_Ï€\Ì€a΀bÓ‚ZЄ[Ï_Ï]ЄaÎaÓT΃m΂iÏ~[Ó|VÑ{SÌ|VÇuYÉyVÊ}aÌ~_Ì}WÌ€]Æ}aÉ|[Æ`ÌcËcу^Í\Ê‚fË€dÏ„cÈ~bÍ~aÍ€aÉ~aÊ}_Î}TÇjÊ~\Èz[Èy\µqb¼r\¹kX¸teЃdÖuÜ–màœtávâ uÜŸtÞœpá¡páußràšiášnßœkÜ™mß›oßkášnØ™nØ•pÔhבhõË‹úØžû߯ýݠ㸪k[±kS¹rV¿xZÃ|\ÂxVÂ~aÆcÈ„\¥^QW&6R':Y3D^*=f6;f1=^09i7<âŸnãœgá«å¡uç¤nê©rì§oí¦né¢häžkâžmâ oç¡pæ›lÚ‡U¼kN›RD¡[Jª[H­gX¯eN±gL¬fK±cM²iVµiP¸lN¸pW¿qVÃsQÇyWÇ{[È~[Í‚bËzZÎYÏ€ZË]Ë|^Ï€`Ð~\Ï}UÈ|^΀cÒ‡mÕˆhÒWÕ~[×XÒ€]Ï~YÏ|YÎ{YÈvYËwWÉ|VÍ~ZÆ{[Àz`Å|ZÌ|UÍcÈ~^ʃiɃfË‚bÊ~bÊeÒZÐ`È~`Ï[Ë|`Ð}YЀ\È~dÏ{WË~aÃu\À{eºoS´m_Àwb΀dÕŒpØ”oÜ™sÝštàžwÝ›pÞžwÞ xÞœuß™qàhà›räkà›gášhÝ™ràšlØ—nÕ‘kØ‘e׌[ç®xùÔ˜úÜ¡ûà±ùÔ•ÄŠ^®gQ»pT¿uW¾}bÀzZÊaÐ…f›[KW'8U,>Y-?Z,>e6Ba.:`3Bd4=Z,6å¡häŸgå£xä¦zçªyé§xê£oç¢iç ræ¡nèŸdçŸlèŸjæša؈\¼fKœSD¢ZG«YJ±pe´dL±eP°eQ¯eQ¯bP²cHÀkMÀrRÁx\Ãx[Ä}_ÄvWÊxWÍ{WÈ€fÆ{[ÌyUË|cÎ}\Ë|\Ò{WÑ~YÍ€^ÑcÏ|XÓ}WуbÑ^Ï…mÔcÑzWÐ}[ÍzTÏ~YÍzPÂtRÍySÃvVÇxQÅsTÈyVÌ~[Èa̓fÍdÏcÐ~YÊ~`Í€dÏdÎ|VËdÍzZÑUË]Í{WÉxVÇx_ÀuY»u^¼t^»lV½r^Ì‚iÔ‹lÔ“zÙ•sÜž{àxÞŸwÝšsážrâtßšháœgß™lÞšká ß™fß™mݘlÚ•kÙjÚ`׌]Ö_öˈùÚ¤úÞ§üÞ¥òÆ…¨dO­kR´qY»oSÃ|`ʃa¢aQ[.>W-AW*:\3C`3B`4@`7Ib,:_-:Z);äžlãjâ yé§té©|çgãœqåžfä wê¥eäŸfåkè¡kç˜]ÛˆY´jQ–RE¢`O­`L®cOµjU°bJ®bI®fM³fOµhR¼kSÄw^ÅxSÅvSËYÇ{ZÇcÏ|[Ê‚gÉ{WÎYÍeщsÑZÍhÊ}\Ð…gÍ~YÒ€bÔƒdÒ]Ó|VÑ„cÒ~UÎ~]ÒYË~bÅzfɃuÈ«§È¨©Àšš½†·yhÁvXÎ|UÈvTÈz\Èz]Íy[Ç€aËcÒ]Í‚bÌ|[Ô^ÎdÑ}PÊ‚dσaÍ€_Çy`Âw]»nT½oR²k\¼s_ÆkÓŠkÕ’tؘyÛ˜tÜ–mÞxßœ|Ü›sâšjßœqà™mãžhäœcßqß™hà•dÙ•oÖŒaÚdÚŽ]ÙcÔmå©múЋúݦûß«ù×™Õšb¯jS¯kSµo]À}[¢^OY+:U+;U)?`1D\1Bk>Jb3Ci7H_/;_/;]1?ã£rå¢né pçªrê£uç™aã“[Þ“bäœmè¢eæ¡mä sè£sæ›hß‹\ºoR£[PŸWG­_L­dP°eO±hQ­eOµjN±eM½kMÂsUÁpRÈvSÊxUÆxVÍ}WÌ}VÏVÈ~]Ï^Ò~ZÒ]Ò…hÓYÊyZÒbÈ{]Ï„dÖ[ЄbÕ„XÒ}VÌ}eË‘‚¼Ž¾œ–¾‘‰ÌŸ‹Î¡Õ²–Ñ´˜Ø¶ÙÆ´Ô¼¬Ô¯ŸÕ»§¿»s[¼sYÊgÆyYÉ{XǃlÅ~g΂aÎ}]Í{XÐiÊ~aÉ~_Î~`ÍxRÁw\Às\ºrc¶kWµpaÌ|^ØŠgבnÖ‘s×nÜ—rÛ–qÝ™sàšpÜ•hà™mÞ–iá›lå›eà—gÛ–lß–gÛ^Öa×fÚ\ÖŒ]ÔgÕ‘dôăùÙ¨úÞ¤üá©÷ˉ®kQ¶pW¾|`Ÿ\LT%8X1HX0D`0>c7Ab6@a8Gf>La-:[):c/<b/<æ¡qè¡jê§jé§oç›là‘\܇]Ü…Rãšdè£fä£wæ¢né¢iæ›fÞ[»hHSE¡VG§]M«fT´gN³jQ®lWºiQ¶iP¼nPºkPÅw[Ð{QÍyTËySÏ}VÏcÑ~WÐ~[Ï[Í€_Õ‚[ÑaÔ[Ñ‚]ÐzVÑ}UÏ~ZÓ€[ÑzVÏaÉ|ÀϜ†»ƒwÆ‹vË¢šÈ¯¯Ì¨Ð´©Ñ²ŸÎ³ªÊ †Îª”Ö®Š×¾£Û¿¯ß¿Î¯ ³jYÄuZÄt_Ä|bÅgÍ^ÈlÏ€\ÍcÎ{WÏ}XÈw_ÉwXÀqY¿oX¸qZ±jU»s_Í„fÖŒdØ’uÓvÚnÚ”pÛ–uÚ˜wà˜lß”bÝ—lâ˜pÞ•là–eÝ•cÛ”hÜ‹^ÙŽgÖlÙ‹^×_ÔŒ[׋YÓˆ\ß™gúÏŠøܦúà¬ÿà¨ä¶„Ây[¦gO_-9T%;V+<[.>b2;i;H_-8d3?^4F\+8c1:\*6],9åžgë£rí­uë¥qä•YÙNÓ{LÙŠZçœhê£dë¥mé§oì¨lçŸgÜ„V·kO›M@ UG¨[F«aM¬_H¯_I³dM¯bL³gO¶fO¹kRÅpQÇtUÑzTÍyRÊyZÐzVÎ~[Ì~]ÍzYÓXÐ|[Ò\Ð\Ñ}ZË{^Ñ„kÉ„qÍ•…Áx_ĉqÆzÀŽ~È”‹Ë”|Í”tÉ“ÅÊ‘vÍž…Ó¢{Õ²™×¯‹Òº¦Ò·¢Õ¬Ù¼›Õ»«ãÈ¥ßÄ°Àž”¼oU¿sZÉ|cÊeÍ{_Çx_ЀcÈwXÈw]Çy[ÂoS¾rXÀpQ´iS±m]½oSÍ`׌iÙ“lÜ•wÖ’oÛ“oÚ”sÖ•wÙ˜uÜmÜ”hÜ”iÚ’hÜ—kÙ‘bÜŽ`Ý‘hÚ‘mØgØŒaÙŽ`ÙŽdÙ^Õ‹_Ñ…^î·uùÚ©ûÞ§ÿä®ÿÚ—¾xXX,AQ';U&8W0Ae9Ce1>h8G`3<[2E`/Ag9Fa8L[,=_.:çŸjí©hí©kègá‹YÈnB½lKÛ‡[åœfè©sí¦më£nî¥kè¡náŽXÀoOšYK•LH›VK¢\S­ng¯dJ¬aL²aI³fK±hTÃnUÂqPÉvRÃv[É|\ÇzZÎyPÐzQÏzVЀ_ÑiÑ_Í€aÑyWÓ‡kÖ•qÊu¾„j„nÂ~m³vh¿j¸|s»rÀŒ„Æ̤—ǜǬ£Ñ¦’ұɧԩŠ×°‰ÙÀ©Ñ¶£Ü·…ÚÁ¦ãÁ•ÚįâÁ£Ûů¬jZ½lRÁpV¿zcÆy]ÄzaÃs[ÅzaÄv^Àt]¿sU¹p_²lY²fNºpZÇ}j׈gÜ’nÞ”mÙjÛ“jÛ”kÛ“uÛ“nÜ—oà•kÙaÛ`×fÜ’fÛfÜ‘aÚ‘h×eØŒeÚ]ÛŽZÜ]Ú_Ö‰_ØŽdùÉŠüÜ þä²ÿå­¾pLT-AY-EX/?a2@j8Gc4Ei=K`.?X+@d3Ac5Fb1A^-:g29è©rï­oêœaå•_ÏxI¢RAÄqKÛŒ\åžeë¨ré¤jé£mï¦méš_ÜŒ^¿lIJD—TI£VG¥]K¢]N­aJ±jN°fO°fP²jU´oZ½sZÉsLÃrSÇrRÇuRË{]È}`ÆvYÍ|\Ï}aÐzWÍz\î°y¹mR½ze¿vU¹zg½|h¸zfº…|Ä…l¸t‹wÅ‚eÅ„kÀ”‡Â€Í¥ŒÀŽÇŸ™Ô¡yÓ°—×·¥Ûº™Ô½¤Ú¹¥Þ¿™Ö´§ßŸٿ´ßÇ«ÞÁ¥·™Ž®lY·kT¿ubÄvWÀs]ÇuW¿s[ÆsVÂpT¹pW·jP¨h^¹lUÍ`ØŒmß”mÜ”nÝ“jÜmÚ’k×’qÛ’oÝ“lÞ™oÛdÙ‡Zà`ÞŒ\Û—lÞ]ÙŽ`ÚiÕŠ`ÛŽbÕŒdØ’jÙ‘jØŒ`Ø_è¤mÿÛ¥ÿä³ï»wK&=U*=W*:Z.?j;Gc5Ag4@\,:T(=^->^/:V+7_.;f6AW'4ì¨uèœhÚ„R­^E’JD¿qMÛ‰Vä¡mí¥mé£ié¥ué¤eèœl߇Y¹jO’F>”M?›[N¥ZK§bR«aN§aO«eR®eM³dIµjOºqZÀrS¿tZÃuSÃxWÇw_Æv[Ï€^ËbÐ}[Ð{ZÊyWÄrPÀoZ½v\½u\¾€p¾xm»zd¹}lÈvº‰½†tÌ‘xĉtɉkÇŠqË—~Ó£}Ó²˜Ò³¥Ô¦|Ó¸¤Ö¶©Ü¾žÙ·¥à½—Ú¿¦âãØźÝìÙǺáÈ°Ó½®¬fT°jY¶iRºoU¼pX¾r\ºr_»p[±iY¹jN©aP¶oYÐ_ߎcá˜nݘtá”iÛmÖŽjÓŽiÖlÜiÚ”qß“fÚfÞdÞcÝaÛ‘iÙeÞcØŒcÙeÜhÝ_ÜŽ`ÜŽaÞ”jÞ•fÿˆó¸uU';V*@T,CZ.<f;De6Fe5?a/@]0@c7Ja6G^2C[.Bn<F[+6E2ï­vð¢bâ”`ÈxOSE–QD¿mNÝŒXçžeìªlëªtë¤hè¢iê›fÛŒc¼lJL@•OF¢VF§`L°fT¦_R°eP°aI¨eY®hS±kY»lPÀqY¾tZÄuSÈyWËvRÎzSÉz^Ï}XÎxUÎuV؈W»v_¿v[¼sY»t`µrc½|oÃ{^Šn¼ƒtÄ…rÈ€dÁ|j¿’‘Ê–{È•ˆ»ŒƒÊ‘€Õ£‚×´—Ï¡Ù¸”Ô¹¡ã¼‡ÛÁ§Ü¸–áǯàÀ¬ßǮٻ¢Üdzݦá˵ßàœ\P ^LªbK°k[¹lV´pb´iT¶lb¶hPµfO±iYÏ|dÝmã˜iâ˜jà˜oÝ”mØŽfІiЃdЂc׌gÞ˜qÝ‘bß’gà‘ká–sáŽYÜi׌fÚ_Ø‘iÙŽbÝ’bÞ’fà“cß•kå›lÕˆ[b3E\2FV.B^/>d3>f4>g6A_1>Q(;e;Ga1?U,?c5En@Lk<G@3^Xí¥gæœm܃O¥]Q’PD˜PEÁrVÝŠSè¡nì¥líªnì£nì gèšbÛ‡Y·hLIB–SLžVM§^N©aN®bR©dS¯eN¯cO®dP·kV²oTÀtVÅv^¾qUÆz^Ìz]Ë{^Ð{YÅz_É{[ÚŽi½pTÁrR¾pNÁqUÁ|g»pZ¼rYÍ‚h¾}iÇŠqº‰zËuÂ…iņjÅ”ƒÂŠuÉ’„ɘ‚Å‹~ÚµÖ´™Ø²›ÞÁ¥Ø²¡ÝÀžØµ ßÀ¤Ù¿²àÄ¥Ô¾¯ÛÀŸÌ»¼ßÒÇìÝËóãÔçÞÈ™TH­dS¸lTµnX«dU³lX¯dS©e\³k\Ò†lÞpå—aåkãšvß™p׎cÎ^ÃqZ½rUÒ„bÜfâ”eá“gß`ß•jß_Ý`Ù‘dÝ’pÞ‘gÝ‘jÛkÞ”gâ–jâ™rà–gk5FW*;W'=X*;`3Bk6Cc6Bf0;X.<i;Cb2A\5Fa1@f7Cl?IJ&=vFQÞŸzæ¤zá’cÃqM–O@—SLœTG¾rRÝeéœaì¥lí¦fé§oé¥pè›cÜŠ`ºhJ’JA“PH¥\L¥]T¯aM¨\J¦dR­hW¬fS°gV³lY·lT¾sSºoUÄz^É|\Ì{]ËyYÅx\Ì{VÎ_Ò~T¸mV»mQ¹o^ÂuW¹qX½wbÁx\¼{fÂ|d¿lÃv\ÂnÂ{eÆ‚eĆmÒ¡„Ë’y΀ÁŽ‰×©…غ Û«‘ÛÁ«Ó³ªàŪٷœâÆ«Öº©Ô°›ÖÉ¿çÓ½æÑ¿åÖÌçÖÄì×ÅôâÌ×»©—SJ£cX®gS®dU¬eV©aQ£]P·m[Í€dÝjã˜nã™há™qâšqÝ“qÒ€^ª`MžUI½mVÓ‹mâ–ià”eßgß’bÞgÝ‘mÝŒ^ß’gÜ“iÜŽaÞ’eß”iâ™qç›l•OJU1D]9HX$5Z.:g7Hd5@d5BX-@b6Ag;EU(<V*<a7K}PWg<Pk<CÉ‘~â¥wâ•`Ó~QžUI WL ZM£UCÀqUÜŽ\éfí©hí§hê§rê£tç™gÚ‰^µiK–RK”RK¡XI¥cR­dP¯fR«]K°hW²hXµiR¹kR¶nVºv[ÂoS¾u\ÃvYÌyTËyXÊyRÈ_Ø„UµeN¶hPµlWÂt\Ãx^Á}]¿tS¿{i´qa´l`Ã~eÀ„qÈhƃsÈ}_É…gËuÍ’|È–€Ì™‡Õ©‰Ü¾¢ÜªˆÝ¾¦ß½¨Ü»Ñ­—̳¸áÐÇéÓ¶åѽäлäÒ¾æϸàÎÇèÓ¿îÜÄòàĨvk™VM§_Q¥fY«aS¨cT®cQªhVÍdØŠhå™iá˜iâ˜sã™tÞ’kÎ\¡_M~@?¡ZHÌfÚnä“cß_à•kÞ“gà‘aÝ`Ûbâ`ßgà‘fã•qêœhÇtQT)?Y,B[(9a-6i<Ih6@e6AZ-=]2?m<@Y):\.?^4CpFVnBT}KT·…zΓuЕrà‹U²eNœUG [IŸXFŸTH½oRÚdä¡sì¥lí©pê§vè¥jä—`ׂQ»iM“NB”QB£\N¢aR«^K¯dO¯fU±fU®fZ­fV¹oV»nRÂoTÇsVÃt[ÌxYÊxWÍ}[ÈyYÎZ³lYºnUºlS¶ta»pUÂv]¶pZÅ€`ÀiµulÅaɈoćpÇ}ÁmÇeÑ–~ÑsÒ—wË‘x΋yؤ{Õ°‘Ùª‘Û¾¨ÏžŠÇ¥“âÊ¿æÓÆçÍ·ãÎÀãǨâÏÆãνãΰæÏÁáÐÂãÕÌìßÍñÞ¿•\Q•OCœWM¥^PŸ]R¤^Q³gUÌyWÛeá™qå›kæšlá”oß“gÒƒh®jYm3B|::¼mSÓ…gÞ”oâ•màŽaÝ“gÜhÝ’kß`à•là_ä‘eé˜lߌ]b1@[0A\+<_-<k:C^/;g6B],?X*;f:B_1B\/H`6Df=OoIZLWµ~tΘˆÅsÉmÍxQœVL \QŸ[M [HœTEÁoNÝYè¡nç¤uí§mé£pë¤hè™_Ú…S²dH‘NF’UMŸ[P«aP¬]N­bN¯_F¨YI®cMµhQ³dK¶uh»nRÅuTÄvRÀsTÆ{aÊzYÌ{bºmT»mN¾sY½oR»kTÂzc¾v[¼s[¶n[³tfÃybÇaË„fÍ“xËqĉyÏuÕ“wΈfÉŽtËsБzà«‚Û¶•Ö¤ƒÈzáȶåηêʦàÅ·äÒÈäκâȵãɸàȵÞɼäÖÈéÔ»êÔ»ëÞÑìàÔçÚ¼‡G>ŒNH“UL™WK¤YJªfXÊ~bÜlæšlä™oä˜há˜má’jÓ‡j«i\f19^0EšaXÃwZÛ‹fá•nÞ‘lߎbßcàŽ_Ý`ߎhà‘få–mçŸxAET%9\3AY*<e4Ah6@h7E^->Y,@n:BY.;X5D].<]4EmHY‚R`¬ytÈ‘wјu¾…nÔžy£[JWN¢YH¤^QœVCZP¼jNÚŠ[äšfì©tí¨xë§vë¨}ä–cÙˆj¹jP‘NJ’KF¢WI©aN§`Q¬dR¨cN­`H¬dO±iY´gR¸q[ÄsSÈsP¿t[ÃwZË{_ÃuZË{XÂsXºnTºnU¼pWÅrWÁoR³n`µ}t¼p½u¸yg¸yeÈ^ÒŠfÇ|ÇŽqÑ‘nŇlÏjË‘x΋tΑzݲĕ†Å¦‘æʪåÊ°ãÊ´áͼèÏ°ãŨÛÁ¹Ûþà̼ç̯æǦÛıßÏÄàÏÀãÒÀæÓÃîÝÌÏÍÇšj\ŽJA“M?œYM¨_LÏ}[Ühå›zä™nä•lå˜nà“j؈f°dKk08R)<t;>²dQÔˆkÝ‘jã•dáaÙŽhÞŒ`Þhä•iç”hë™fÇtRX+<Q(:S(9b3?g;Cg4Aa.9\.Al;Fk9@W,?`5Ff:GfARsFY©xÊ‘|Εzº†uКw×¢‚˜UL¡YH ZL¥[H¡XJŸVE¾qPØaåšgê¤rì¤oé£pæ£tæše؆^½kM”OD•MD UF©`N¨fV¯cL«eR¬dM®hZ¯fO¸gLºmW¹pUÁvZÃu[Èu[ÈuSÖ‰d¼pYÀnPÆsS¸n\·o^¸mUÃz\¸ubÇzZÀsZÆgÄŽ}¼€rÈiÑŽvÎwÇ’‰Í‰nÎŽtÇ‚dÃ}Ê–Ó™vÁ}gÛ¼ªÞĬßÈ´åʨàÁ¨áÇ·ÜŵâɲàŨÚÀ²áÁšâÎÂä̹áÎÀæÏ»âÒÇãÒÅæÒÄêØÆìÚÉðáŲw_ˆGA”QC§_KÐzXÜká™oá™rã™pãœrÝ›yÕˆb´jRn5<V*<[*8ŽNH¼t[Ù‡aá’bå‘aÝŽeÜkáŒ]å•mè™rß‘jc-5S&:W'7],;m;Ck6Be7CY,<_->j5<a.@Z-:_3>\0Di9OšjeÈ‘wÆsÉ’uО†Ö¥ƒÙ£~œUG¤[H¡^N¢]L›VHŸ]U¼udÚˆUæšiè¢oç¦}ê¦zë£pç˜aÝ„U·hT’LF—KA\Q¦aKªe]¯hZ¸hM«cO¬bN³aM¸pW¶mT¾nPÂwTÃvW¼oXÃrPÏ|W¬^J®aMºkQÁsWºlU·jVÃtX¹mY´ulºx_Æ~dÈnÇ{ΆkʉkÒ”xȆlÇ€pÃ…hχg͉b¾r½ƒÜ²’Þ¿³ãÆ´ÞÀ«ßƵݺ¡ØùàÄ°Ù®äпâÍÂçѽãÅ°â̼äͶæϸâʱäкâпçÙËæÕÃçÚÍðáÀt;<‰F@¦^LËyXÛŠcá–kæšqçšpâšqäšwÖˆc±kSt;BZ(6U%5m15§[GÍzVÛŽkà’eÜfÛ‹aßeä”kèœp’SOV+9a2?].;p:Cd2=e4Ac1@Y,@i;J]+8_1=b09Y2@W.J•fkÇ’ÆtÀŠxÉ•wר…×¥~Ò ~ŸXL¦_Jž`S¡]LžYL›UL¿oQÛŒcãŸwè¥kè¢qè£uå£räœr؆gµiRNP–ULYKŸ[I¨`P²dP©aM¬eS²hO¯fQ¸gL¸nUÆvW¿sWÁw\½oW캀ÊoH½jM·m[ºnW¿vaÂoO¿pUºr[Ì{ZÄd»yjÇzj͆jÒ–x¹zqÐ…fÕ“uË}Ä{_¿{g¹s]°paÜ­}ä¿–Þ¼­â³ŒßµàÀ¤Ù¶ÝÁ¬ØÁµâĪàË´ãÏÁâοàÉÁâοãÓÆãϹæоãÐÀàË·ÝÊ¿âÐÀæÖÀëÚÁíâϵ¥­{8>—SIÆvXÜgã™râ™lçšoäœuÝ—uÕ†c³iUw:?]-=_.;[(7s45¯aJÐ{SÕŽkÚŠ\Þ†UÜŒ`å•iÎyLW)9V+<_0Aa2=f0=c6<h5C[/A`2Ac4?X,>i5@c7AP(?}KUÁ’ƒÌ–ÄŠpÇ“{Ó¡zÓŸvÔ¢}Ø£y¡YH XIžZO [NžXFšQEµjOØ‘käšdë¢jë¢rê¦sè¥væ™iÜ‹\ºnV’OF’OK¡VH¤]N©aK­`G²eOªaPªgT²m]¸mS±mYÂoRÁtY»mP¹k^úÈ€°`T°iY³fUÁsY»nSÁsTµlTÁu^ÇvZÑ}WÃiÌ…lÏ…eÐŽiÆ‚h΀]щnÄy¹yh±n^µzpßµ¥ßÀ¡áÁ©â½™ß¼Ÿà¸œÝ¯‰Õ·¦âÇ°ÞÅ·ßɽ۽´ÞʶâÐÁáÈ·ßʾá̹ãκֿ·âÌÀåθãÓÅãнâÓÅåÖÊéßÔðàÈšXPJFÂpL܈aä˜fã•kß—qå—gãœuÖ‡d°gRx>K`.C](4^,6S".p=EÏ¿¹éØÆîÕ¹Ù¾±æÓ¿Ø“ob/AU*<[.@^1=f1=h9Ff;Gh9K`8H^-8^0Gh8Hb1;[/=d7K»…yÑ—yŇpÃwÔ£„Ó xÓŸ|ÒŸƒÕžy™XK¡\LšYK[O¢]RšUFºkOÕŒhåšlé¥wæ¤w䦈é¡mæ—c؉^¸fHŒEB–PGžVFXGª^Jª^N§bL¨]I­eW°mV±eOºjO¸mSÀpO·eOÏŠ`î¥e´fU±iP´mU¸q]Î|UºmWÃsW¼{j´iZÊiÎ_ÏŽnÁ~nЈaÀƒp̆jÄxW´yf´rfÊ™‹Ü²£Ý¯ƒäº“جš×¯™àƱԯ¢âÅ£ßÀ¨ÝÅ°ßÄ«àIJß˸â¦ÜÅ·á̻ܿ¨Ùòäнç϶Ýȼà̹àÎÀàÐÁãÒÆãÒÆåÕËèÞÖÑú‡GA·nWÔ‡lãšqå˜lå›häœsá•kÖˆh´kSr;A[)7Z'8U'8Q.AâγíÕ´Õ¶¤äпíßËíâÔéÔ±L&AQ,CZ-Ah3@d3?gAKa2?`1?d5Cb4Dc4Gj<AT)<Z-C§uwÏ—€ÆzËvÒœwÔ©€Ö¡‚Öž{ÔxÕŸ|—TPœZM¥_N¢]NŸZQžTH¸mR×…Yã˜iì£tì¨uë§xé¡oèlÙ„WºjI†C?KG›SE£ZJ©`N°bL¯cK¬bL«`P²dM¶kVµiPÁsV½nR³bQüÖ–í«r°fO¶kU¼mQ¿jOÁv\¿r_ÅrOÇyTÁ{`Ç~bÑ€WÅ…i­dZÔŒeЉk¾xe¹q\®eYߦ€Þ¯èºØ¢س•Ù·©Û¡~Ú°—Ú»­Û¹Ý¾à½›Þ¼¡ß¿¬ÛøÚúڻ¢ØÁ´å̹áÉ´âʱáÉ´âÇ£Üǹà̽ßÊ»ÞÌ»ÞÉ·àÏÄçÛÎçÝÇ‚LK³jVÕˆbà—näœpä™oç›qá™sÕ…_ªgQk07M$5I%;‚`pèÔ¼áƧÐÉÌîÝÊíÝÈíÛËôáÊöêÕU3MN';Y*;a0Bi5Cf17\+<f8Da.8W.Bk:Da-<X.CŠWhΕ~Í’~½‹yÏ›†Õž†Õ wÕ¥{Ó }Ó ‚Óœt[R¢WE¦_P¨cK§ZDŸO@³iQÕŠfåšgê¨oî¨nè¨zé¥påšcÙ„V¯fM‘PFPG›WM©aP°hV«cM±dP²cN·fJ¶hL³jP¸jLÁsV¹s`³gXýÓ—ã’[¬`N®gS²iSÀoQ¿sQ­fX¼iJÎ]̃o¼t]ÇyZºzi̓bÊ~`Æ‚^²oU§f`ݨ‰Ù±§Û´Ù¦‡Ò¨£ß·ŒÓ¨â·¢Ù¯Õ«–ÞĶÚÀ¯Ü¹ ß¼Ÿà·Þ»Ÿ×º²áʹâȸßÇ·áįàÊ»áǯáȶßƬÝÊÁãÑÂàÑÀäÓÇáÏÁäÒÂæÜÒÙθªZDÔˆ_à›vá›vépæšfÜ–mÐ[¤bO]-<?#:°£¸éÙÄΞyÖƸîÛÁëÕ»æÒÀêÓ½èÕÂøçÏ­‡Q,K\.?_3?d7=c2>a3>d1=V.A_0<e6Ad6Nq?MÁŠ{Ò•uÇ{Ë—‚ÕŸÕž{Õ|ןvÓ}ÕrÕŸ|¥_P§_M¬jbª`Nª^G«]N¹lPÚSã™`ç¥pé¨vê¨qé¦nçoÜb¸mNH@’QI¡VE£\M­aM±gOµeM¶bI®gS·hPµlSµiQÂqRµlRµcNôÏè–\±^K¶lU¶nX³lX°jVÃu]ÇyaÍ~^Âm®gZÉ_ÓˆdÁ{fÒ†aÀrN»q^ܨ‹ßª×¦†Û¢ŠÖ©ˆÕ˜ݶ¡á¹×ªœÚ±œÜµ’Ù­™×²¬Ûº«Ø¸§× ~àÁ¥ß»¦ßÆ´àǸáǬàÇ°ã¿—áÊ»áÅ®àÑÈàÀ£×Á³ÜÌÁÞÍÁÞÌÀÝÎÁàÒÈåØ̶¢¬ÕSà”eæ›fèœiäœqß[ÂrQ”WP`9JОæѹƣ—ãÐÂêÖ¾æÑ·æзÜȺà̹êÚÌõâʶ’wL)A[1Ge8F_/9\.@e5?^2Fa.;h6:Z,;\1E§ppÒŸ‡Ì’}Ê•xÔŸyØŸÓ›yÔ~ÓuÑ›wÕœyÕŸz¦eQ®\K³cK­`H§_S©XB½jKÛ‡Vå›jé¢jê¤ré©qî©têžeØŠ[µkR–OHšQC¤YE©\H¬fSµhN·dL·lS±`F¶eLÀrT¿nNÀqV¾lOу\øДքP­eO®dP±dO¼pZÎyRÂ~l¸mYÉvYÇ€f¿xjÎ{\Í„fÃ}d²fT·{lÞ¡‚Ù™wÔŠÐz஄֞‰Ù­á°†Ù°—á¿›Úª‰Þ³‘Ö®—Ù´—Ñ«¦Ô­—些߾¥Ü´žÝ½©àÇ·ÜÀ©ÞÄ°áÊ´âɸÝÈ·Æ›†àȲÞɺà˹ÜȸÞȲÝʼÛȺáÑÅçÔÁÑÀ¹à^ä˜cç˜fäšk׉]µpWºœ ìÛÁÕ²•Î²­ç×ÆèÓÀäκá˸ÞÄ®äË·éÔÀëÚÈôãË›l_R)>[2Dd5Cc0:_/9\.=d6Jm8Cf3<J 5}KXÏ–ƒÐ•€ÆŽ|ÕŸƒ× ‰× ‚ÓÓžvÔ™rԀњwÓ™€°iW©_I²bG®fL®bI¬ZBÇoJÚiå™bè¢qè§sê§nì©né kÝŠ_½qO–PA—QE SEªbP°lY°cI³fK±jP±_D¹dJ´fJµqW¹pV°gVé¯wðºrÊyT´jQ´fO¹hO½hR¾nQ³n[¿t_ÅwXÇ{aÉdÌx[Å‚b²l^È…oÜ£xØž|Ö‘wňwËuØwݱ‘Þ­“׸¤Û¨ŠØª™×»¬Þ°ŽÝ±‹Ó¡‡Õ­˜Û¾¨Ü´žÜ·—׺®áºšÞ¿«ÝÀ²áÉ·ÞȺàưˤŽÜèÖÁµÝįÞDZß˺ÝÇ·ÜÇ»Ù÷Úįß˾âͳã’Yåœgä”ZÝ`Ó™ˆãÑÁäÇ£Û¦ÚƵæÔÁåѸãɲâ˺ÝÈ·âË´âϾç×ÎêÚÎñÝ¿O*@R/Fb<P_.Ac2>^.8[,=d2Cf4?W*6Z-B¶uÓ›…ÈzЙƒ×£zÒ Õ|֞јzÓ€Ö›yјzÒ™v¬dM±`F®cO«dP¯aH«`IÉqHߌ]ߘiê¥pì¨sï®sí¬sé¢mߎ]¼nK˜OC“MCYK¦bTªbK±aG®`I²hP±`I°eL·kO½lL¹lR§YKûڥ᥄ËzTµhQ¸mV²bM®aP¾qQ¹qZ§_YÉyYÇ|c²fUÌ{[½ubДƒÖšÚšnÒ“qЗx¸xlÛ €Ø¦ØŸ‹Ø±Û¤‘Ӣפ—×¼·Þ¸™Ó”{Û»žÛ©Ò¯žà¿ªÚ²Œ×± Ü¼¬×®›ß¿¨Û¬‡×°¤×µŸß½žØ»£Ô·¦Ù¾­ÙĶ׼¯ÛÀ²ÞįØĸӵŸÑ¼µÙƽرŸß“`à—ißïîÔ«ÖµŸ×±ŸäÔ¿åÏ´àÈ´ÞʸáDZßÊ·âιãͼæÑ¿ëÔÂñàÏñÞºL'@W2G\2Da2A^0>]+:Z-:d3@c8Io>N™^cÏ“|Д~Î’xÖž}Ö €Ö }Öž~ÓŸ~Ö {Ñš}̖јzÑ–x­gN®dP­gQ·gK°aH°`HÆqMÛŠ_ålì¤gî©kì®uî«uê¦sà”h»oQ“J<“NB¤bU¥[I­dN±cJ³cJ­cK®_G¬aK´fN·jKµeG¥XOýÖ—èžnÙ‹ZÃwT¸kT¸nR·gSÄvTµnZºhPÆzWÀzoÍeÀsTÌxÔ•{Û™sÏ„fÕ¡†Ãx_Ú’qÙ ‚Ûž„Р’Õ™…Ú¨ŽÕ²£Ù­†Í—Ó¡“Þ·šÝ¥ƒÜ¯”Ù¯•Ý¶–ݵŽÞª„×·¬Û½®×©‡Ü²ŒÞ¼¥Ó·®Ó°˜Ø¾¬ÖÁ¾ÜÄ´Þ¿¦Ø¸¢Ùº¨×»­Õ¾®Ñ»¬ÖÁ¶Ó¸¬ÛƸٱ êӷ׳‘߸•ßÈ´èϵå̳ÞÊ·ßʶàȳãÊ·áÏ»â˹ßÆ«æÑÀçÒÁðàÑïÞ¸E$AZ/@`5D^3J^/<W+9e4Eh5Fi8M~KVăӖ€È„Ñ™yÔ¡„מ{ÖŸ‚ÑœxÑ›wԀќƒÒ›xÏ–yÑ™y¯cP«aK§VD¬gW³dE²bKÃoQÙŠ^å˜cí§uî«vñ¯tð­pí¦nâŽ\ÁrR—RC˜SB¢YE°[D®_I«aK±dQªdM¯aH°_E®cO·hL³fL«_VúÓ‘í´€ä’ZÔ„\ЃW´iR°cP½iK½s^¾kPÎ…dÈ~h½xlÃpÓ‘oЈfÑŠlÖ˜q½{h×jÒ’{Í‘{К‡Ö›ƒÙ¤„Òª©Ý­|Õ¡Õ¥‹Û»¢Ù©„á°Ó¨‹×°£Ù¯ŒÚ§Þ´Û­–Û¸§Ýµ—Ý·žØ°‘Ù¹¡ÞÅ°Ö·ªÙ¾¯Øµ­Ù»°Ö°”Öº¬Ñ³¯Ï¶ªÍ±¢Ã¤Ð³£á̹ܴáǤÞñæÒ½æϺá¤ßȱàȲÞdzàʹäθáʶàòھ¨åμèÔÁðÚÀÙÊ¿Q&=Z-=^->c3A^->k>Pj7?a3<h9N§tvÙš{Ó”~Ï•€Ó …ÚŸÔ }×}ÔŸ„ÖœzÔœtϞљzÖ›vÒ™z©^Hª_J¯iW¨_J®eL®aI¼hGÛŽ`ådé¦kí­|îªqñ¯vì¢oàTÄtN’K@˜OB¤[KªbN®cH°eS¯aI®aK¯`I¯dK´iO¶eK°gM­`RüÎŒê²äžg×dÒ“c¿mJ¼hN¾x_²mX½r\¾v`»p_ÁƒvЇlÕkÒ‡hÕ’k·ucÚ“s×”rØ™wȃkÍŒwÕ­—׳ŸÙ¡{ÌŠtಙ߱†Õª˜Ý¬ŠáªˆÜ²˜Ü§ˆÚ²Ø¨’Ö¥}ۦݴ›Ü³–Õ´šà¸¡Ü¬…Ù½³Ø¾­Ù«–Ú¶ Ö·¤Ø­‹Õ²’Ú¸¡Í®Æ¡˜â̾޹—Ò¸®Ûijá˺çÍ·á˶ÙĸßȲàȲÝÆ´àÇ·àÊ»ãÈ·äÒÂÒ£†Ùª‰æÌ·äÊ®í׿t=;T%8Z.=`3Cc:MS%6[,:f6C_0F~GVÍ“{Ó“zГ{Ïž‚Õœ|מuן}Ö ƒ×Ÿ‚ÓžƒÕ¢wÔuÔžvÖŸz×›yªbJ§`O¨\F«aN±bJ¯^CÀoQÚŒdæœjí¬sì±€í­pê«pë¦pâŽ]¹nW–OD”RL¤`R©cM±dNªcO¬`I­cK¯cK°gP¶fM¶hL¶fL¦\Oùǃï¬vêhÛŽbßa¿qSÁoK§]P²bOÊwT»mTË€gÕpÎ|\ÔˆjÇ™y½waÖ”uؘ|Ö•{Õ•sÒ˜„Ù›}Â…vÒ£›Î•~಑ݨŽÚ¤ˆÙ©žÜ©Úž}×­¡×žzÚ§–Ø›‰Ø®’Òšx̪œÖ«’۱ܶ—Û¼¥×®Ù¯™Ô°£Ù¬Ö±£×´¢Î¤—ϧ¡Ñ´œçÄ–Ù´›Ù½¬à̼æË®âȲۻšÜ¿§ÝƳáÈ´ÞȸßʶßÈ´âʺâȬ׮ŒÌœ‡Ô°•Ç‹oÞ¾ªéÕ³P,C\1>].Aa5Aa2?[)7a0;Y-=Pa­y|Ó—{Ò’rÍ—€Ôž‡Ö „Ó¢ˆÙŸ€Õ¡‹Òœ€ÒžÒ~Ñ€Ôž}Ô›sÖšqªbI¥_L¦WH§aL¦bM°bLÁpKÛŠXçfì¨vê©uè¬uê«ví¤iá’`»jM“ME™NG¦\F§dS«dT°bI«^IªbO®aM®`F·hM·fF¬`G­eMôÃ{é­{â’cÝ’jÙŒeË}X´k\§]N¸hQ»kMËŒqÕkÏ`ЇgÏ‹cÁ~fÖqÖnÌ‘ÏvÔœuʘ”Û¢xÖ•~Ó’wÙ¦™ÚžxÜš„Û­˜ÚŸ~Ø¥„Û Õ•}ݱ‘Û£‡ÕfÌž„׫ŒÖ®’Ù¨‡Ü¯šØ«™Û¸¡Ø¯’Õ§“Ò¬›Ô­™Õ´¥Ê ŽÑ§˜èʥб™Üº™ÜIJèαáȶÙñÜÀ¯Ü¾©àÄ°ÞűáȲàȵâ̺ãͼäͺåϻș†×¯»}kÒ¡‘Ü·šË¹«N%9W)5c8D^0:U+:f6>\-:n?R˜`hÕ•xÔ—‚Ë“Øž‚Õ£€ÓŸ~ÖšwÓ‚ÒÕžzÒ™xÕœrÐœ~ÒŸ{Óœ~Ñš{§^G§]I¥]J¨^H¥[H«aOÅnLß[è¡fì©uí©pì©pñ©qí©kà‘e·kR™SK˜RN¢XK«`K«\L­^J¯^H¯cM±aD´gN³dH¬cM¨]IÆ}QòÀ€æ±}Þ›zÚ‘qÌyVчfÇv[¶cI²dN׋iÕŽpÔ‡hʃgǃdÉ‚fוxÖ‡aÍŽzÕ‘jÊ‹sÐxÔ–xÒuÓ”|Ü¡yÙ™~ÖÙ•t՞ћ„Ñ¢’Û¥œÛ«‰ÑŽpÅ•ˆ×¬ˆÛ¡Û­˜ÓŸ†Ù±šØ®¡Ó¤ž×§šÖ¢‘Ö¨”Óœ…Ç—ÊŸàÁ¤Ý­…⼋àèæ͵äǬâÁžÝîÚ­ßÅ°áŪßȵáʺã̸á˵ßʹãÑÁçҺʛ‡Ð¨Ä‰tÙ©•Í—‡çиS.@Y1K[1=a8@];MY*;c2@\/EyG\¼ƒvÖš|Î{Ζ„Óž}Ó €ÐžƒÒ›ÑšxÓžƒÓ¡ƒÕž‚Л}ÏwΚyΙvÕšw¥]F­cO«_J¨bNªaJ²fIÇvVߌ\ä mì§tí­së­xí¯{ê¡hâ—k¾qR•K@—J@žXG£_N­fR¬aK®]D³`H®cMªbM®cL«`F¡WGáš^õÄ~í¯sêœ]â“RÚ‚Sá”_ÌuO»bGÑiÖŠj˃hÇdÃ|`Â~kÙ“oÏ…c×–uÐ’vº|pĉ~Ó–yÑŒjØ”uÚ¡Ú™~Ô•ÉÏ›µ”˜©Š’£uvX^Ë–Š×š{Ý£Ù¢‚ؤ|Ñœ‰Ý¥ƒØ›…Ò •Ó¢”ТžÐ«¥Ñ˜{Ä—Ú¹žåÀ–Ù²›ÛÁ±å̳áãڻ¤Õ¸ Û¿©ßÀ©ÞůÝDzÝƯàË·ã̺ä˺âÊ´áͽæÓÂÝÇ´Î¥‘ÅŒzÏšj«l`بŽîßÀI$=V+?a8J]3AX.?iBPc1=d6J•aeÖ˜yÑ”€Ì“yÒ‚× €Ø yÕž€ÓšzÑštÔ›~Õž}Óœ€Ðš|П{Óœ}ЀԜs§]J«bN­cJ©dP±cL·hQÈuRàŒZæŸoì®sì«pê­xí©lð«uàZ½kK–KA—PG¢ZF§bS©_K°^F®_F®`L¶fN¯_GµbH¯]F¡TFØ’NòÇò¯nížTì Yç [ìœ^ÛˆV¸oaÎaÈx_̃iË‘†¸|nÌŒuÚŽkÑŠqÒl¹{fÇ„nÍŒvЊ`Ô–yÒ”}Ó–ƒŽSZ«}€©mgUYžjjž_aÊ‹Ì™ˆ\c½ƒt٠ة•°Ž‹Â‰~ר˜×¨•«xh7LÊ›’½ŽŒÆŽ‚áÁ®ÚªÚ»­âdzèȪãÆ­Ú½ªÜÁ©ÛÄ°ÜÁ®ÛƲàȳßÆ°âÈ´â͸ßɲä̹æйæÒ¿æÒ»Ò§ŒÆ™z‰QJžcW¼‡…ëÕ¿À˜oL"6Y-?`18[(7_0Cl9?\1Ei7L¹‚tÙœwÌ’†Ï—~ÔŸ{Ù¢|Ö ƒÓšzЂњ|ÔœzÒŸ|Óœ~Ôš|ЛwÑ|Ïœ‚Îœ|©dT«cT¨dS«bL­aP¶eLÐwRáŒWéiì©sîªqì®wì®|í§nå—c¾qR”LCKA›TE¥bQ«^H°cL±dO²eL·hO¶aG²bJ°`BŸVDÐPöË÷»‚øµeì¤\éšYéžcâX¹o^Ãt\Æ{eÁ‚rº{oȉuЇcЇiÍuµ}n΂eɇtʆmÏt×”zÓ‘s«q€ÍŠq»xm¦jk‘]hZeoE\Ö¦›Ø£Ÿ€¤©†¢ ƒqE_‹\k rq”ai_2KlEb†^nR,I̜彙С…Ôµ¡ßÀ¤àŪܾ áƬÙñÛõÝÀ­ÝÅ­ÞɺáɸáʲâɶåηáÌ»à˵æθçϳΞƒ—XD•TH\N´xkâÁ­ìÚ¹T,AT)<_/=a.9X)7f3=^/:X0F”dgÒ–Е͔֢…ÓŸ†ÖÓžÕŸzКwÑœ|Óš{Ïœ|ÒœzΛЛ~Ì™ЙyÔšy¬^K±gQ§bQ©_M°eMÇmEÑtLä’[êžbê¬rê¬líªsì¬pî¥gã—i¾sOPH–K@TJ§]JªdP«_G®cM°fR¯aL±`J³bH°dM§XD´cEýÃxù¾jþÅjñ£VÙ‹\è˜[¿va¶q_½tYÀl®jaÈ‚j͉nÈ„nÒŽqÊ€dÈ„mÒˆiÈ…lȉwÓ‘zÊŽžemĉ¬~‡¢q{£di¯ty“eƒ‰g†žp†¥Š¨†YpmHed;\—€Ÿc;ZtNoX.?P'AS4VL,N ‰”Ô˜tÓ¥˜ÞȸæÈ«áèÞìÞÁ§âÅ«ÚįØÁ°ÜÁ§ÝDZáÈ´âȯáɺæмãÍ»çÏ¿äÈ«Á|P’RF—`RšZI `P±q_Ý´œìѲD5R-@[0Bb3Ba3>V+8i9CY.<Z.Gº…|Ê”„ÌŽvÒš‚Ô¥ƒÔ€ÔŸ}ÔŸÓ ‚ҀϚÔ™yÏœ‹Ñ›yÍ™ΙzÌš~Òž~Ò™u®fL«cO±fK®bIµjPÀoNÒzKàŒWæ¡pêªxê¨oí­lî­wí§uæ•cµmO•OG’SK [J¤aL«_H®gS°`J°eL­`LµbG®_F¬`D­Z?šRVûʃýË|ÿÊwó®[ÓzSØœ{Ì”vÇxT¹v^­iXÇ~dÒŽmΈsÅ…j¼x_̆sȇẍiË}hÑŽrÓ‡j©kiĈx€u©qt¯uƒžnxIUh<UoAQ{Rk}YpŠa‹…cˆo>V‚e‡^3Iƒd‹]5M?1E&Bͳ¦¾ƒu̱®äÅ©àĦâƪá©Þĩݾ§áÃ¥ßñ׿©Û¿­ÝÄ«Û°ã͸åɬëÒ»åÍ®›\M–RG—TE˜VHž\N¨iaÊ—ˆæ¹˜ê˨a03U'=X,=c3A`.=^-?c2<f9AR*B†UcΓ|Ì{ϘyÕ¢Ö¡€Ó †Ö¢†Ô£‹Õ }Ò}Ò›|ÑŸ‚ЉЛ~Κ€Ï™wÌš}ÏÍ—z¯iS´eK¯bL«`J°bKÅoQÐwRß“eåžlëªjí«ré¯ví¬lí¨væ’`ÀpN“RJ”RO ]N§ZM¨\K­`G¯dO­`L«\E±aJ³^BªdO¨[E—ROøÛ­ýÍzýÎ~ð¥WÚƒRÐwÄzeÉ€g§`P¶n^Ì…n͇tÈŠ|»}kÂw[ΈpÄuÄyaÖnÕŽt±mk¹Í‹w¬r‚€^pi;W|Ljl=Si;RsDf‰by~Rhf9Q‹`~„]k|^ŠZ0MzD ;a?aÞÁ£±toÕµ¤åĢذŒÕ³žÛÁ©Ü¼§ÝÀ£Ù¼¤Ú¼¨Ú¿©ÚįÛÄ°ÝÅ´áDZÝǵâÈ©œhT¦~¤`P›VHœ[M¯n_Ï”yã¢n嶑åǦ^->_1?`4A`5Cd3>_,;[-<k?KjL]Z0P²zqÓ—xÇ‹rÒ¤ŠØ¤‚Ö¥…Ó¡‰Õ¤ÑŸ~Ë›„Т‡Ï›ΞΛÌœ‚ÔwÌ™yИyÌ™‚Ì–v´iR°jV°gP±hX²hT»gEÏyPÞ”nçœcì©sé©vë­uë¬wí§sæ”]ÂtV’MB“L=œSB¥[J­]K±fR¨ZH­`F¬eO¬`M¸dF±fL®bJŸVKâ©[ûÈuüÊy÷ÁtÕ¢sÛ™yÖ…X«k^ÂwbÓqÐŒuȃo°nbÂ~tÎjÊ„f¼|oÑ‹uÕˆgÒ‡m­ouÆ…z‹\ne8So“a2Da7S_0Gb1Q™u“‘dk]/EZ,Gƒ[t^€U+BE#Kv]„jBZá²…½€nßÀ«âÀسٴ˜Ùº£Û¶¢Ù¸¢Ù¹£Ú¹¢Û¾«Ù¼¤Ù¾§ÝÀ©ÝíÝÅ°»ŽkzNS–gq²¼Ž‡Ô’jæ£xê¨tߧ|é­‚îÊ¡\*4V/B^-@kAO`7Hd2A\/;\)8m:BZ0EtBRÎ’|Ð’wÎŽxÖ¤ŒÖ¤…Õ¥ƒÓ£‡Öž|Ò¢‹Ð£ÒƒÒ¥Ê™‚Í›{Ì›‚ќ̀˙Ë–‚É–‚¯kY´hPµl\¨_M¯aIÃjKÍrJáZéŸhì«që¬~é«sî­lïªtã”_ÅrM—TP’LE XK£[LªdP©^K­aI­dO®dQ°cO­aJ¯dN°dPª^G¨ZGüÐŒüÓœøόܩ‹Öœ‹Ñ“sµlXÉ„nψiÌ‹q©c]ÉxYÇvÆzbÀw\Éx§utŒNTЊy«ojp>SfA[€U_c@RZ-EqFYX+@oFjM\a1Ec8U’s‹‹g‹Q'Ata”@4†_lÙl¸€nÝ´åǦٷ•Ô±¢Õ»­×µ™Ñµ¤Ð¯–Õ´žØ¸¡àÁ¨ÞÁªÛ°áĤг~PSpBJ›v~Ÿx„¶•’Þ¦†å¥yè©vå¦ré·’òÍŸa.1U';\-8_.;l8Ab7?a1;^-7d4>`>O\7K£pmÒ“sÏ’xÓžƒ×£~Ö¥€Ô¤…Ó¦ŠÖ£‚Ô£…ÒžÒŸ‚шΟ͈Μ„Í˛ʙ}ΖtÍ–y°kV³iW²fR²dK¸dG²fGÈrNá‰Vé¡jë«rî«oê©tî¬uì©yâ’aÊuP–NF’GCžWH¤\IªcO°bJ«_K¬bM°aJ±eM®`K·fL¶eF¯`FŸZLöܱúÚ¥î½ä­„á›q¥YIÓŒoÌ…oʉ{£b^ÀzhÆ{b»znÆy`σkÕŠoÏŠv|<E•\iyOfmE_Žg‘nD_X*F“w™R&@V(Hk;C[-B]*BŠ_o|TruQilMoO*F†n”ÊpºsäÁžåĪ޿¬Ó¸§ÕµÑ¯¢Óµ Í®Ô®”ͪ–Ö»¤àÁ­Ý¾ŸÝÀ·qS€FOzGN—mz°‹€žtqšioÉæ©xí®zë´†ìÊ–_2;R"0]*8`2=d4>h:Gc4Ad5D]+6f28X0Ae:N¸„|ÇxÊ‘|Ö¤|Ú§~ק€Ö¤„ب†×¡Ñ£‡Ò¢€Ó¡~Ñ ÍœÒÎœ€ÍŸ‰Í„Í›‡Ì™ΘµjS±mW·iP¯gU®bL³\CÂoNÛŠ^èaê«wì­|ï®sí«oì¦nä•`ÇuRJ?”NGšNH¥[J©_N­aJ²gQ¯aK°bM¯^G¯cP¹iLµhN·iQ®bLžWKøݵñ»}è°€íº}¾wSË{_͆p·rfÁ{c΀dÇ~jÀvc²rq̇w­|„·vp¥fgŽ[ii>XƒZlY.EQ&AoB`ŽhuP$8a2P^1=[.@a/Db5Nf>TW-NŠ€¢”p…†QW›n~⼒Ῡݪ׺£Ñµ¡Ï±™Ô· Ô®’Ѩ׷ Õº§Õ¹¢Ö»§×µ¦ëĪ竉’SRšoo„RT‘ez¦‚‹kvÇ“„å©ñ ⷃV,<\.9U%4b3?h5@k9Ap?G^1;U)8\+>c6Bb8NŒXXÀ‡sµqКƒÖ¨‚Ù¨†×¢~Ô¥ˆÕ¢€Ö¢„Ô£„Ö¡‚ÑžÒ£Ò¢ˆÐ€Ñœ|Ïš€Í}ʘ{Ç•~Ë–|±jW·jVµiR­cM°gSª_N½iMÖŠ`è mîªyï©píªuð¯qñªkã˜gÊxY“KCF<—RA¡]K®gR¦aR¬_J²aL­bM¬bT¯eL´eNÀkQÁnP³gJ¢WHçµuöÆ{ð¼”Û™s݈[¿v_»rbÀxcÊ‚j½€|³umºup²€Š u‡•e{P_…OcŒ[lŽc|k?Ra9LO'A~Z{j?RrA][*=^/Ci<T€Xw…b€`‚qNzs’Ÿ{ŸœuŒÆ£¡ã¾¦Û¸ Õº£Òµ£Ñ±šÏ±ŸÒ¯™Ó®–Ô¨ŒÒ³¤Ð´¨Üº©ç¿©èÁ«ïË°å¼—Ë|g–ZYxmŠ\f–id«„‡ÀŽŠç¶ˆ—YI_,9X+<b4De,<g7Ak8Aj9Bn9Aa-A`+8l7>[/CqH_§vk¹€m±€~Ó£†Ù¦Õ£×£‚×¥Õ¡Ô£…Ö£†Õ¡|Ó Ï›|ÑœyÑŸ~Í…ÐxÌ˘zÏ›|È•€»qX¶kV·kS®_J¬`K¥ZFµgJÚƒUã™gê«xì¬kë«xï°yïªvä”dÆwV“IDHD˜XJ¡UG°eOªbP¨_Lª_J¬^M¯bL±cLµjPÃqX½ye»oS¥_OЂPüÙ”öÄð«w¾wdÇ|d¥_TÁ{hÁzg¸}yȇpÏ„k³qr̃n°qusAVf;Qh9SŠaqCZ\2KZ3PpB^e†vK_X-?]/@`4FZ.>W1D\4M“h|}X†Œj’§‹“Òª”Õ­˜ÖµžÒ°šÌ©Ñ´ Ï®›Ó°”ײ›Ð°™Íª™êĥ뿩êÁ¯ëÄ­îÅ®ïÄ¡ãšw²aHHS–mv…P_¬ƒ†·ÃŠzœSBT$5S):^/@f;Ji8?m;Bi6Ba0<X-=a0<h2:\0E€N[ºŠ{­yrÁŒxÓ¦†Ö£€Ö¥‚ؤ~Ò¡ƒÓ£„Ó¥…Ô£‚ÓŸ‚Ó €Ñ Ô¡‚ÑÒžƒÐ|Ï›zÏ|Ê•xΚu¯cP³hS´lU­`J¯cL¥W@´jQÙ„Xâ›mí«~ë­w첆í¬~ð«på—fÆwQ‘NI’NK›WL£[K«bN®bQ«cM©bM¹dI±cM¶dN½jKÁqUÅvWºiK±cJÐ|PüÚ¦û×¥ÍuM½v\¹tc¾we¸ub°fWÛŠiÐbÉ„pŸ][“SFf3?tHZ[3GU*CqE_qEZ„ZtS,Df7Q~Z€’nW+=c8FT)7S(:N$?˜irOS¦ˆ©À–‘ܳ’Ô²™Û» ×´Î¨ŽÎ¤ŠÑ¤–ÓµŸÌ¢‡Ë¦œä¸˜ëâíÆ­ëƨë«ìÅ«îĨïÁœé¨~¶dLy<>W+AˆU]žpl±ј†o4AY,<[/<f0>i4;rDRe8Dj4@]-;_0>`/=e5D_.F¦tn¿ˆv±}q–„Ó¤դץ€Ô¤Õ¦}Π‚Õ €Ñ£ƒÖ¥€Ó£}Ò¡ˆÒŸzÓ£‡ÑŸƒÑ ƒÑzЃИqÍ—v±jV¬hR¬bO«fU­dQ¡]J·jOÙ‡_åšjê¨{í¬uì®zêªví§uå—hÆuQ–RJ”K=•OC¤]N«_J°bQ¶eN«fW«_K²iS´eN¸lR¾nTÆsR½mUºgI³cKÿÖšþͯgS¶gN¼oZ¹wm¼p]΄q¾mYÊ{gÆ{h—hnR%;[oZ.>W)@].B]5OwPlqHZb8SSo`9\¡°|Pi~W{O);F!7ª…ƒ¨e_Äž Ó¤‹¡†Ÿ×®’Ú¿¦ÞÁ§Òª“΢ɟ‹Ñµ Õ°™ß¢‰ç¬‰ì»žíǪëäíÈ©ïǨòË­ñ϶óͳì´ÊlJ‹JE\/APQwDQ»’ÍŠ]0HY3E]-:c1:f1>f6Ej8Bh3;g6F\'4f19X1?uHTµ†u¹†uÆxË›}Ä“v˘Ô¤ƒÖ©…Ó¥ƒÓ¤|Ò¢~Õ£Ò¤Õ¢…Ô Ñ›yРҠ~Ï{ÍŸ~ΙzÌ–wÊ”{­cN«lX±iV¬dN§bO¨[E®cN؆^á™hë¨rë«zì­|ë«sî­ræ“dÇzZ“PJQIœTD¢]M«eO®kU°l[¶cJ²hO±hY´fMµgTÄ{RÃrXÆvTºlN²`Pýàºè´ƒ¹jPÀwi½mQ­h^Í‚dÆw\PSxHQ„IQ“[_\.D‡[nU*<l@Yl@U\.Dd:Nh9I_4PzPkb:[‰o|[-BM%;G4˜okÂs_П›Ý©‡×¥‹žˆ¢¹¢ÜÀ¯Ô¶žÓ«‘Φ–Ϩ”Ðyãž~çª鹑íÁ¦ïÇ©íʳðʱðƯóкòÒ¸öÓ´ñÄŸÕ†f©YDS&:\,@ƒOb½ž¡Êž^7IZ/An4;e6?h:Ei7Ak>Ea2>_0A`4Af69Z-E˜hiÄo²|iΘwÑž…Ê—yÄ—‚Ë“~˘}ÍœƒÏž†Ñ¢}ÓŸzÔ£СŠÒ£ƒÐ ƒÔ¤~Ðœ{Ñ›zÒœwÒ}Θ~Ì•}±lT­gQ®eOªgR©gT¥[E±fHÔ…aãjê«zë¬wì¯uí®sî§nä–e½pW•SM™SJ UE£^S°cO°fU±jW²gQ´bJ®aQ¶cNÔ†bÅrQÃqQÄtWÄsS·mZã™S伕ÇtPÄoP»r\Á}hÈ„y×…k³g[™Y[`4GT&:f9Wo@K[.Ik>QlAUa7KX)AqG_g7S‹f‡…X{[,?k@_C9ŠY]ЄlÌ’‚ܪ‡Û­‘׫—©Ñ¦‰Ø¾®Ó³šÑ¬šÌ¦‘Ø‘náœ訄䮑ëÀ¢ëÀ¥îĪíɹðʲñͱñÒ»õÑ·õÓºóɨã™z¦WBa.;Q":vJR¿¢Ï¤’]6IfI`i8Di:Fh=Fl>Gr<C_->^/<d49`4D`5I¶uÀŽ‚ÈrÓ¦€ÌŸ†Ë›{ȘxÇ–É”vÈ–~É•zÊ–{Ç–‚Î~Ò …ÑŸ„Ï¢†Î†Í‡Òž{Ñ›wÎœ€Í˜yΔu±gP¶hO­bR®eQ¦\K§^I¯fSЀYáœkê¨xì«vì°té­uð¨kà—gÄuT“PKPM`W¨^R«bL¬fU¯eS´jV·iP²fT´fOÅ…j¿qZÃ|\ÌyUÇvWÈrM¿qaóØ´Ê~]ºcMχoÌ„mÇv`ª]QAC\2L\xQ':V)Flo<RjAR`/EqFWY/@c8Q]+LZ-:sH`P$E‰hf4BÓŠbÁ{hÞ¦…ଅڼ¥×¹¨¦†ŽÔ«“ßȷѧŽÑ¡ˆÝ—uâ æ©„æªé«Œë·‘îÀ£íÇ­îƧðË«ñ̲îδòÑ´öÔ½öѯꪄ½kUz8:P(=Y*<‹PSΪ¡‡PV_0Bh6@g7Fg9Bl<Dk<C]1@]0?f8>X-;„RWÈ“€´‚rɘ~צ|ңѣ‡Ïœ}Éœ~Ìœ{É—}É›ƒÀs¿’~Å’uÇ‘uÇ“xÊš~ÍŸˆÏšyÊ™|Î~Λ֛{Ï”w°fP«cQ¯fQ¬cN©]H©[B´dKØŠaæ”gè¨}쫀ꮆï°tï«uâ›uÆvW•TL—OH YR¥_O°gS±gZ¯eS´mX±eS¸gR¸lS¾pZ½sWÁpTÀkIÁoL¼fGÓŒfÊQÂtQ×XÕŒx¯‘¡lmr8DXrO$Ck?TmIrf;VU(>l=VƒSgZ(;a7Mf?Td:L_1EoEl}RuH7†a}Ú p¹sbà¥zÛœzÛ¯•Ö¹¦Úº¦«Š×·ŸË§›ÎƒÜŠáŸ‚䥂鮑笄賙붛ïÁ îÅ®ìɵîÇ©ñ˪ðͯóÏ´÷Ò´öѮ︗ÉtT”PFU,BR(A†PZÙ­‘HO_,:d=Ok<@m?Ji?Ja5<b/;c2<c5A\2I¥wvÂŒo½ˆvÍ¡Ó£~Ò¡‚Í ~΢…ӢϢƒÏ£Ñš}Ë›yÀ˜…Àtǘ{”}¿’„½wÈ“yË—|Æ–}ΚxϘwЙy°fO±fP«cR¬]G¬aH¥ZE¯dPÚ†aâžrç©‚ë­ì¯ví¯yð«pà”eÆsO•OJ”OF¢XO§^O­gX³dP­fU¸iS´hV¹hR´jS¿qPÂrSË{XÎzWÍxTÐwQ¢aSå›bÉ}`¿}³…‰¾p\­i]Y3RuK_L%F]oT)BP#<qC_‚Vcg5D\/EZ0HrX*Ci=[cAXL#5F ?ÀŒy—YUḑ٧ڥ‚Ѩڽ«ØÀ¬Ð®žÍ­˜Ó•vࠂ⧋⤉å©é¯ê¯é±•ë±•ï¸”íĦë¦ïŨïǪñͲòϳöÕ»÷ѲóÅŸÔ] NBR%9T+?O_Ú²”YVa2GyJQnCQmCJl@L^/=a4Fd4>]3AnAS½‰sÁ†mÅ’}Ô£sئ‡Ô¢…ÐuΠ„Ô¤Ò¦„Ó¥‹Ï¡†Íž|ǘ€¿•¿‘€¿‘v¿w¾sÓÀz½Ž|Ä“‚ДqÉš|­dQ¯fP§_L°dP®eM°`Fª_KÕ‚Yâ›rç¨wï®{뱂ð±xí§pã˜lÆwU•PJ–RNžZO¥`S­hQ³fVª`O­cM©_Q²gY¿kQÄrPÉuWÄuYÊwYÙ–pÝ¥[S#4U&:ªmg´‰Æy]ÀqRb.FpFRN$@\4M”q•S&4h8H]0Ch?UV)=[,C`3Kf6IX/Bi8T[wQ(?¢yr¦_PáÅ·Û¥€Ü¹˜Ì™Ó¤ŠÛÁ´Ü¿«Í¯•‹G@­eQ·tcÉ|hØ“ä¥ëµ˜ëµ’걎벑췚îáëÁ¢ï¾¡ïšïȦñɨóÍ°ó̪뮈ÃoRt7?Y&3P%9‘_tݹ©Ÿ^Zn>Gc8Ji=LrIRh<Ha3A^1Cd3>[2JŽ]a¾‹|»€jÈ—zÑ¢‡ÒzÔžyÏ}Ïž|ÏzÓ …Ñž~С‚ÌšzÍž€Í›vÇ™ƒ½”¿•‰Ä•¿‘‚¼‹y¼‘…¹‹|À‹v‰q°iT³fP°fP­aF²`C¥^K¬\HÕ„[ãwé§vï®{ì­oî¯{ð©påœkÃv^“RNOHœRKª]L±eT°bK®bP¯eT¼jM¸fH»kRÁsXÇoUÃrSËz[é¡o¸oVo=G[(A´ŒŠÚƒP UISRb5L‘¤T.S}Yz’oˆS'=g;XmLZc:NW0AV'9P%8ŠlŠnMr‚[T)D`:EÄ€eÊ›ŒÝªƒÜ¹à½œÍš‚Ø»¬ÞíɑoÖˆkÞ–z×”xÄ}e’KB=;›XMÒté¯ç´˜ç®Œì¯Šíº—é¨íºí¼ŸòÄ™ðßé¹Ãfž^UŽH@‰C=X'6O*AsCUÙ¬›ÃŒwY-?}HLm;Cn>I\4C]0<b0<g6DZ-@¦vsÁ‰w²qÓ¢†Ù¥wÓž|ПÑœxÐuΛО}ÌŸÓŸ|ÈœƒËšÉšyÉ›~Ç›„Èœ‡Èœ‡Çš†Á|½{´Š´ˆ}¶†w«fY°hU±jW¯hR°`G¤S?ª`LÙ~Rã–rì§yî«pë°~î°sð­yäšlËxS“MLSOŸZP¦`O¯tj°eV¯eS°dP°cP¯eQ²dM»jNÀqUЇlâŸ}ÝhÀ‹Ž^\M*H¹†Š§_W—YQd4M‡h‹^3MrNn]0D—…N%>vKgS(?^7HyL_P!0\)6U*C‚lqX1=E 8Òž»€sà¨zß²’àÆ­Ò¨ŽÖ±ßÆ©¸lOÑ~_ÒŠnÓŠnÈ{^àœ„Ó‰l²dX£VG¤YNÌw]å£éªŠê®ì¹šíÁŸîº™ì¶™ê¶µmYŸ_[®h^¶lVÇrN¨ZCs:@Q(<qCWÏ¢’·€ne1:m@GtALo?F_8G`4Be0=d4?k<O»‡z¶nÃvÑŸzÔ }Ö£ƒÏš‚Ѐͅπ͙wÑžОzÍ›wÍ™{É–v˘yÈŸ…È™~˙Ț†Æ—|·“‚°‰²„{±s®jU¯aJ¯cO°cLª]H¢TB­_KÕ‚\ã™gë«tí®yñ²uí³yî¨uãœgÎa–L?•MD¡XJ¢_X®dRµiR³dK²fN¶aI³cHµfL¶nbº‡~ÙiÝ›xß›wð¥jâ˜kÁzeo7@W-Bo\o|Qq‡`zyHfƒh€F <~\}U&<|YrO%;V.JuQ(9\-:^-8U%6i<cžob­dPæ¹…Ý°‹â¡àÇ´Ô«™ÞŨ–OE¤WCWF}BAp85l23u7;g0;½{kшrÒz]ÑzXÝmæ¡è£‚îÁ¡ðÄ¢ïÁ¡ë»ÔŠh³lXv99k35r8@zAC†AAn27S(>sHUÙ®p_yDLf;@m<Kh7=a0>e1;c0;S&>†RX¿•Š¸„r̘|Ö¤}Õ ~Óœ‚ÏšvÕœrÍœzјvΞÎxÏ|ИrϘzʘwÊœxÉ™}Ê›ƒÊšƒÆ–~À’zÕ»}ºŽ³‡‚©`J§_P¤^Q¨\L¡ZL˜QCŸXIÑ‚\â›jê«zð²vì±nð²vì«{ä—eÌzT’ME’OG—TE¡TE¨^J¶cJ­_H¨_J¯aJ«\H­aZÓ¥ç¤fÞ[à˜uâ–i¾„zb2AIHH"CxY|Nm“€«…f‰‰eœ­A:|Wtg>R}^rV,EL#6U)B˜xšS&:]'7K);K#:É•gÛ¹¥Ü¤|ß·¢äÌ·Þ¿«Û½ŸŒJ<ˆB>h.5l29h5Ac-8rNažno[-9\(9¨V=ׇ`Õ‚cÜpâ”u꧄レôÌ°òÊ¥·uXf4A_2CƒGHv=@d/=k<Dz:<f-8R$2vDQÁ”‹·„}}IQd7?j:Bc09^3@d7Fg>JQ(A£mdŠnÀ†vÕ ÒžvÐœ€Ï—xÏ—yΗtÓ™nÔ¢Óž„Ï›yÎ}ЙwÆ–xÎœ|È–vË–{Èš„Ç™}À’|¿Žz¸Š{¿‰x³‹¶ˆ{¨dM¤\K¦]F§`L¡YG“PEŸS?ׂVâ˜gï­oî­lî±…ñ´ƒë¬~â“]ËyO‘HC•NF¨YI±eP°aI¯^H¯gP°dJ­\E¥WHÔ~IñćÅ~fÜ‘kã˜dŸ][Ìs€GOK*EoPtb=V}_…L&@nHl‰b†pŽQ)=Z->]7Mf>HW,AV(6d2C^.>Z,@b8WQ&E¸Œu®l`ܤtà·“Ú¸£àȶâÅ ŽPI–N?i6<j37PN„NWS&3f2HãËÆѹ¬};CšSNÍ|gÐyW݆dàc裂óÇ¥ø×´Èdb2@W/Gn9LƒKO¿’Žp7>e19j7Ce1<U&9PW»Š€ÃŒ€˜kxi:En?Ga,8^09`2?_/Ag9K¾‰yÆ‹qÇ’~ÓœwКwÑ›zΕwЙ{И~К{Ï›{ЗtÍ—{ΚwÍ™}Ñ™yÉ—}Ë—|Ã’}É–|¹„¹‹v·‰x·ˆv´‡}ªw®ƒu©aL«_G¯aI \NšYK•NFŸOAÒYãšjëªuë±zï´yð´tí«rä™dÍ{S—NE˜PD¥ZFª^G·gN¶iQ´iN²fS³hRKCo9B‹U_è§x鲉âœcj.3`2GP)G{Wv_.HlKo^4U_5VpJe…Yz‘qM*?[.BX(7Z,D{OcT)7]0@^,;Y+;Q,EQ/@QU×±¡Â“‰Ï³ªãȲßä¨gVÃwa­dT‘NJŒDF¶kl<EŠOQ›qŠæÑËìζÅzkÐ~\ÁkRÇr\×~^Þpë¦|õΰðÕ²£\R—]b”ciŒY[¦zŽØ›‹†E>a-5h/7f6AW*<fo¬rhÈš…`eU\g4<]/9d4Ee5CY->‚RXÂ}¾†tÌ—€Ñ›}Óž€Òž}ΘoÐœ{Ï™xÍ–~Òœ}ÑšuÊ—xÏš|ΗyÌ—‚Ê”nÔyÃ’wÂyÀz¼|¶ˆr±†u¦~w²Š~É£‰°dLªdQ¨aK¥`O[M“M@–QFÓ|Oá—pï«tï³yì³zò²{ð®zã˜kÐyRVG YL¬aJ³hM³jS¾nTµhOC5n4B‰Ui¯„Ó¯¶ìºŽõã·^3JO&<K(?pIj‡b†[2K]6YZyyUkeƒb8S™ƒŸ_;SS'6[+;\(8^1Co>M`/:g6EM#4W8[Ì›„½‡{Ô–tÙ¹ ßƺÚÁ¤ªeOÏ{]Ñ}j׋oÊ…t¥ZO¼n`ÂŒ‰¼‘”áÁ¯íκ綋ܑmÇpXÓ}WÑx\ÕcÞs驈÷ÜÁéÊ°¨YKÇ€t£y©Ž«×´¯ÒŒD<{>Eq5>Z/Bb3EˆW_Z`Ë¢•}JT‚SW`1>[-8[0>j9?\/B˜f_¿‡kÃŒwÔž€Î›|ÏœzÏ—wЛ{Ó˜sÏ—yÏ™wИvÑ›s̘v˘zΕwÌ’sÄ•Ô{»{¶‡q»´„q®xÁ’yÏ¢Ú­}à·Œ±hP®hU­fO¡XCŸVH™RG˜K<ÕUãžhêªvî²}î´ï¹‚ð´vå›oÓ€U¢VJ¢YI²dK·iL¾pT¿qSÓ›xV'9©niÖ™{ÆŠ†Æ““£tOa<ZR.R—¥~[gc:S]3JI%@v`}vYz]5R‡eŠŽg‘’m…jE`O&=S%9Y*9_,>`/<b9Jb1BL"6]U£XNàÁ¨Ý°ÞÁ©ÞÅ®ª`LÍtZÑ‚mÕ‡oÛw×mÔ†mÖƒfÅwc·tnÊt½roÏ¢¢Ü°™ÜlÐ}`ÒlØ‚bÚ‰t駊öÚÇìηᧄӓʃnË€c¦XC†<8{??–UCt7;W-C`4E‚OXŠT\Ô¹²‚T_†SUa,<c6Gd3>b4EtBG°|Á…hÄpÏ|Ñz͚ЗxÇ—{Ï–|Ï—uʃʗyÍ–tÌœƒÍ—wÊ“mÆŒv¿ŒvÀz¹‡u³…t³ˆx¹‚֧ݴ†ä¸„潄辉¯iV­bP¥aNžXK™UF“MA’H:Ñ|Sâ—jì©xî³vî¶|ð·…ð°wåžmÕOŸSC£S@¯`J¸dHÁnOÀiNÕŠT½”‰Æ‹ŒÈ¨xERmE[~RcT';[3OZ6\¤ÄœŠ¯‡p”Z5R`:NlEc[…†j‘’vŸš…¨a4?W-CX);`2@[-:^.?X+9G0J":Ó›sÅŒzÚ¦Ù±šáȱ\G½cHÓ„gÙŠtÝ’yá–{Ü‘qÝpÛ”yÝoÔ‰tØ”|Û•zÜŸÚ”ƒØœ‡Ó{b؉p×dÙ‚mç¥óÒ»îÒ¹Úª“Ú•{Ó‡pÏ‚oÊ}d¶gR«_J [D|?@W(9b2BOU€NXàÀ°˜bktAAl8?X&6pDEY)4KPËs²€uÏœzÑ¡€Ë”tΘyÍ–yÊ•|Ê–xË“rÍ—zÈ“wÍ–xÈ“rÊ“wÈ’wÇ‘t¹‰w½‡l´…u±vÏœyß³…ç¼…èÀ…亄齀鼀¬aM¨^HœWI”PG–RE‡C=ŒD;Í|Uã•cê§të°wð³†ð¶ƒô¶ƒæšaÖQŸVJ¡ZG§^EºiL½nQÀmPÃoW×™x³pgŸjgc8Q‹f…c>VP.Ni:Y‚\|’uœiF^uPoT+H`7TuRunNbwªŽpŸƒm†“‡·_0@X,<T'3X*;`7HY0BJ&A°o°eRÚ¬…Ý»©ä˸±O±`HÅoTÔ†sØtß–}à›ˆä¢Šã¦Šäž‹â¡“ßŸ†âª”ଗ㫙ચڌpÙ‡n݈c×~fÙ€lå ƒðÐÁîÖÆ⺜à…Ü—€×‰uЄlÆt[ÄuY«_D‚HNa,4s@G}JSs>Dܹ§—jv‹\__1;U%4e:?T(=›f\º‰{º‰uÍœ‚Ð}Ï›xÍ–pΘwË—|͘xÊ•wÌ•yÉ•wÇ”€Á•‚È•wÂvÄ}¹Ž²€oµ‚pج‚æÀˆìÅ’ëÁ‚鿄羇è»~꽂¦YE WJšTJ“OD“M?†A9ˆEBÎzNâ™nê©uð°wð²uñ¶{ó®rëžiÒ]VDœP?«YA¹cFºpY¿oXÀuf¥k„˪¸¤‘ºª‘¬iC]`9Qe9S{Mn‹h€X€œ…ªL"9Q+F^8Z–{•zW„gDg’{µ¿i@Xp@JY+>`3BX,9T,CU,CU(;Å|RÃŒ€ã´ŒÞÁªÑ»¥ŽD;¿jNÎxZÒ€hÜ‹rá–ã›}檋奇豖䫒嬒魑æ©â­”Þœ~Ü“~ÛŽoÚ‰jØb×z[ä—}îË·ñÜÍâ¸Ý¨—Ýš}ÝmÛ†jÓ~cÐz`°dMo/5f-6j06zBFm:C߯•¥ux{IIpAOW)8c1:_->°zi¾‡qÉtÓŸx·ϖvÌ•uËš„È•|È—|É’xÅ’xË”vÆ’uÃrÀŒu¼}»‹u´‡v¯‚uتêÀ†ëÄîŃìÀ}ê¿„é»}ëÁ…éÀ„›VH™WL”OI’RO‘K>~>;‡A?ÎzWá’cè«ì±}ðµwñ³ï³|çžmÓ€Y›PG›N?§YD°kf™щk´‡Å€otBK`<Xd>Rh?Xc7OtQwvNmtQu—‚¤a<S]7OP(>T*D[6Ih?[‘rsLTK'F±…z§uh]4G\.>W/FT.DO*Cµ‰v°plÙ´’Þ¬ÞϱT%7–MAÇoKÐy`ׄgÙˆiá–råš{处讓벓笔簕簌鲗孌á¥Û“xÞ•yÜŒuÜ…a܃iß‘vîʶòÚÈ㸛ऎកÜyÚ†vÕ„kÍ}^¸gMt>Gm;Eh4Bm7Bc/Dâ´•³Ž‡f6Bg4:`5@`/9h4?ÂŽu½‡uјyÓ¡zÍžzÊ™zÉ—É“vÍ•sÈ”xÔwÄ’xÑz½wÄ‘tÑy»Štµ„p¸„qÕ¥zéÀ‰íʼnìćí€ïÁ|êÀ‹è¿…éÂ’éƘ™UJ‘OEŽID‘OI‰JCy;6>?Ê{Uä›pé©të°vï²yï³{ï°å—_Ñ|Q£XH–QG¦]H­na¼mVÀo`·ytxMaXvƒ^|rF\^6R‚`ƒ^6U–„±m„]8UY0HZ.E[/HV)@_4LyIWi:Me5>P'D§lc£ic\/BY4JS)AN&7[2GÃfÄtá½£ßÁ¢M'<f06œUJÇtWÑ|[ÑxSÛŠnã’qä—v⠃譎뵤괓ç«é­‹é¦‡âŸ~Þ“|â”pÛqÛ‡cÖƒaâ–xêƳñßÑ帞ݡˆÚŸÝ•yÝ…iÙ„eÑxS®bLz>Cr=Cl9?k5?c-?Ú¬œË¨Œa/:[)7e5?_1=ŽVNÉ“n‡oÔ zРzΘtÉœŠÆ–wË—~É’vÄ–~Ç‘uÁ“‚É“‚Ãy¾‘„¼Žy¶…u³€sΞ纃ðÀ|îÁ„ìÁ}ìÄ„ë‚鿎ëÆëÉžéË©JGˆFBŽOKŽJDƒC<v@C€A=ËtPÞ“ié§vì­wê¯yï±zð®vç›hÕ€VœRE™RB¡\N²hK»iLÄpY V]¡…¦–xŒ]w†Uk‘r•U5N^7]tWvƒ\uY2Lb4GW.>`3B_3C[0DX5I\.C~C?p:E«qc¼X©zuN+DH 6M!9»…c¶sdâÄ©âÄ®¹—vP(;k17žUHÌtRÏx\Ú‚hÝ…aãqá–zã“mè¢€í©„ê²’é°„ç­‘ç­‹æ¤{㟃ݎhÞŒhÛ‰eÒ{YÝ€XÛ|麧òßÎ㻦ުŠßžÚrÙ‰oÛ„jÌvZTGg3>g1;m3<i-6^*CÚ³œÏƒX*:Q"6m?B`2C­tdËŽnÆrÕ¥}Ï›~ÏšyÊš€ÊšË”xÅ•wÆ”Á“}ÀŽw¿qÂ’z»w»Œx±‚r¹ˆvâ³~íÄïÃíÂyíÁ€ìÇîÅ…êÇí΢íΛë̤†KMJF†JHDG{CFn5C|<;ÊwRß“eé¥rê±{é«sì±}ï©tçšlÔP›TF“LK´ˆ“ª`N¹f[Ú¯°–b;NRr¦z“’| W-Iz_„vV}‡r¨š­€Xr`7Pf8P]1BR&9T*>R&6uADr9<v<F¤†ŽœTRÉ€X‰PKS(5M#:Ä‚e¾tæǯåѵF 7T%3l17ŸTHÅlNÒ|_Ø~XÛ„cáŠnã—uå}å›}ì¢ꭒ謌ç­é¦‚å¢|á˜oÛˆnׄaØŠmÕ}ZÕ|W߉jæ®–óÛÉè˹इÝÚ“yÛŠrÕ„nÌxY†DBW*6`1Bm9Dc/7Z%9Ô¤ŽÅ•Šj<EV-<`8C\+9¿ƒjÆŒpÌ›‚Ó¡|Ò›wÏ™~ÌšyÍš‚Ê”tÆ“xÆ’v¿ŽuÁŽvÀ’}Æw»‰x»‹s®‚iÖ£uêÀ€ïÃïÂxíÁíÁ}íÇ”ïÌ”îСîТëÊŸëʦŒRO…IKƒFGƒGF}CGn5<z=@ÆxVß”cì¦sí®{ì¬ví¯xîªxç˜bÔ€S–PC”I?Ãe¯kmÆ…|°‚•‘ThzGc¢}‘„b|d;W]4Sb†rS|ƒ«˜Ž±š·f=Mc7IV0?Q*=U)=CB¨fQi2C”eyß»§Ç”{{==yFG?4§oZ³~nÙ¾·ãË­T(9R%=Z.:s44›QDÅjJÐ}]ÖƒbÚ~[à‡ià˜€ä™zæ ˆæš{夊穂稆饉ä¡~à™{ÚŠmׂ^Ó‚kÔ|[Ô{UÚˆg樊ðÓ¼ñػނژzÚyÙŠvÔ‚jÀoPy:@U-Aq6;†MJc-8O!<͜Njp‰SUY*7]+:HNÈ‹lĈjÓžuÒŸwÏ›zЙoÑvÊ•}Ê–€Ç•vÇ’zÕ{À‘tÄ’u»‰t¾Œt²†vÅŽx軂îÄ€îÁ~íÁíÂ}ëÇïÌ•ïОîÑ¡êÍŸêË¡íËœŽPKMKƒFH€KNv@>o3:o/3ÈvXà—jã£{í°„ë±xï±{ð¯wêžeÖ~O›QA“MC¡ZG©db§zµˆ–WisGhˆ\|„^‚d8Z€b…ˆuš€^‹{\„Ÿ•²Y5@J$8W-Ha2CV.Da2H‰^o[Z¬zn²uZt;<xB:N$5L .X+Dɉ^¾yeéÍ­ ~VN&9V'?\0<‚A;¢RA½fFÊw\Ö^ß„aà†bãrá˜å—uã~ä˜yæŸ{ç {礃á~ÞpÑ}[Õ|WØŒr×{[ÑtTÛ„j⟈ðѾôÝÇÝœ|Þ˜{Ü“uÔ‰nÕ€_¨dKR(>^,<sDIƒFFl57K4ÁŒzÀ„q¡rtZ,=Y-BšcYÅlňiÖ¡xÏ{ÌœxϘp̘wÊœ…É£ŽÊ”xÃ’xÀ”‚Õ¿x¼‰nº‰v¯€qتyíÃ}ïÄ€î„ïÂ…íÄ…îÍšîÑ î͘ëÌ™íÏŸëÏ¥íΤ–VP‘MF‹PN…C>|?=i.;i/6ÁwYá–lë§uí±„î°xð°…ò¬{ècÒ}W—PA‘KI²|‰´of¯lj»uluE`…[s€\vNizPoa:^’yX5Y€_Ž•†§^0Qi>SY0LkDRS*<K$5†Yb¾ŸŽ¥]L”np;;U(7Y/BF%=Åš†©vg­vdÇ¢i66K"7T$5`-6”NC–M?ÁjKÎyYÓ|YׂaáŒhâ‘oàlâ™xæ—w矇äœz碄äŸ~à’pÙŽlÆkNÚƒ`Þ‹kÝŒmÙ€X؃l枀ñʳöâÇØjÝ”wÖq؃gË|\ŽKGY*;c6C}CAˆLId3<M 3¯ƒ~ÉŸ·‹|c6CR'?¼~h΋dÏ“rКtÑšxÏ›sÈ‘q˘tÊ•yÍ™yÊ™yÉ™„Ç’}ÂtÄ”~¼‰pµk¾Šrç¹}óÇ‚ðÂñÂzïÄ„ïË—ïЙíΚîÌ•ì˘éΫìÑ©êΦQLŠOJQJˆLE@=t:<{:;ÈzXÞ”hè©ë®~ê«wﳂð°æ™iÒU¥dn¨dY\T±dT²oh¸z}|Kb‰\uˆg€WsX.R‡k˜ySrO*Sˆn‘ŽvnBb§¥ÅW,=^0FŒ^cK&=qK^W+9^2CbeX'7J%5J2£ŒŽ×¨†Ø°˜Þ´Œ¤zvS%8O!1X&6e37–\U¡TEÇmLÓzS×}XÚƒdà†`àtãŽlâ–rã˜zã—w⟂ç|å €â–sÜŠbÈlM݈iÙ‚SÏ~bÖ„h×yXÞlíÁ¢ð̱ۗ~ß—{ÕyÕ„_¼v\^,<R,@e5Au:?o:A^(4U#2VSÏ©’°…zP#1X);Ì”tÐnц΀ʘ{ÏšyË”vË–yÇ”vÍ–sÅ–yÅ”yÆ“{Á“v¾Ž~ÃŽs·„uÔ¡yî¾wñÄ|ðÀyðÉîÉŒðÌ—ìÍ™ïÍšíΛëЪëÐ¥êϤêά”US’OGICŒH=„C>EBMDÎ}\á™rè¨té¯ë¯}ï°|ò°{ë oÕƒ`žTG”MC¡YG±cIºoa¤jq¡an†^u¬}xxMmI&N˜€”_<XQ-R‹u¡z§¥´—”§I#8mCIwFLQ%8I$8U+8—t†n6B\2HP':F:Æ—ௌãÀ¦¾¡˜O"2S'6]*7_/:_)1£fa²_GÄlLÏtOØ|[Ú‚aà‰`àpânâ—vã–tç—qå™zä}äžÞ›|ß”sÖ{[Ü€V½lU¹kXºiO»aB×{Vä©Šâ¬Þš€Ø‘v׈oуc’TKV*AQ+Ad2A…FIo5:k/7x;<s:AѬ’Å›‰S)AˆJDÏ”xÎiÖ¡~ΛsÉ™ƒÊ“yÉ•zË—uÉšƒÉ•tÄ’|‘yÄuÃ’xÀ‹w»Šy·„vß«sñÄ‚ðÄzïÇñÇŠòЛîΙìÍ¡íѦíÓ¦ìÒ¦ëУíТìÍ£THšQBJ@‰LG‚?;‡GC YOÏŒwà›sè¤xê«ë«{ï¯~òµ€êŸhÕ…[›TJ’QG¤\E°cNºzw§f^b4Pˆ`~vK]N%H†ži>_yUzyW†}š}b‰ª¡µ“~ L#;f<Jžqs²wi=6M&:sFDG">’`d§oj´—œ¯tY«smØÏÂJ$9S)<jM[c09W"1c4>¢dX«YCÆoRÓx[×~[Ú`Þ†kÞ‹qà‘pâ”rà”uä”wã˜|å ç{äŸtá˜tà•oÚŽzÜ€[߀ZÖfÕŽß¾®ç¼¡ä¦†Ý›Õ‘}Ó„mÇxXX,;X1GU-D]3A…IHs=Aj6<c-2_,C×°’Â|g7E¬ygÏ”rÌmÒŸyÒœtÏ–qËšxÊ•wÌ•xÄ”wÉ‘sÈ—w¿“yÁ‘rºŒy¾p¸„nº„oç¶|óÃ~ñ‚ïÅ…ðÌ“òЙïÎìΟîÏžðѤíÑ¢íÏíЦíÑ­‘RN‹OI“PJLD†HC†FD¢cYÒ‹nâžuìª}è§qí¬uó´€ç oÖˆbšUJ“OIZH°bLºpeÒš”V+O~VvtNq‹wžhC[O-NqLi{Zu‚b€‘}£rOiŽo‡‘o‘\/=wK[¤cXR&@_4@`5F¦u|²…ƒÖ®™˜XL¯th×­V.EV0E^0=`17i6?_.Ac4BŸ_S±cPÇoWÔ|ZÕ[×€[Ý„bߊiãhà‘ráŒkâ˜u䜂枀çžzãœyà™xÞ•zÜrÞlâ™w迥棈êȳåªâ¢|Û’xÔŽrÑb¢`QZ3JX1HU.FyHPŸcL{FAz@Ca-;O!>Ò „¼ŒzŒTQ¿‚cÒ‘bÊ”rÔœù˜~͘}ÎÅwÔwÈ–È’oÊ“p¿’~ÀŽr¼x³‡zÌ—së¼ñÂzðÄ{ïÈòÑœòÑœðΘíÍšñÑðÓ§ìÒ§ìÒ­íÓ§îÔ±ˆLAI@ŒE?I@|>=†GC¤h`ÑŒsàœzè©ê©jî«xñ³~ð¯tè mÔƒ\¡VH”SF£TE®\KÓ——¨|‹mPk|Rl ˆl>M[0B[0Ra9Ng@awQs…eˆyVŠn™™yŠk>X‘`rˆRYL%5M'@¸”•Æ~Ï´¦Í¬ZN«uem?9W(<^+9h3>k:@m<Ec1;^,:£ogª^FÇqUÓzYØ_Ú[܇fàmàrâŒmãŠiã’vâ•uâ–yä›{áœ|Û“wÜ•tÜ”yܘ}穇í̳櫎íÊ®éç㠀ØwÖ‰nφgZ.CW4K[1FV.DrBP•YMIF|?@e-5M7Ƙ€À‰p£rlÐiÕ[ЙpΚwÆš}ÌšzÇ•uÉ—{ΔrÑwÃŒs½‚Á‘oÄ“p¾w»r¹„iÑ›uïÂ~ðÅwóÉ‹òΘòÒ¡òЙïÏšíÎœïЙïÒ¤îÔªíЪîÓ«îÔ²‡ED‡GF‡B<ˆIEzABŒMH `RˈpÝ›xé¦xê¬~믇ð¬zôµ{ê¤pÕ‚XUM•PIžQG½Š¯le®v~oA]‘l‚ˆg…d9XsSrfC]c4RrKcpOq…f{kHr›œ’t„Tbƒ:7T'?ŒXb—_\§wvÉš“ÖÅ­ŸeWœYRÁœbN)Ak5=h6Fs:<t@E~LLb.?]'7e^–I>ÆmLÏ|`Ø\Ü~]ß…gà‡fä‘mߊmã‡bâ‹láqÞ•wà’sá—vÜ“uÝ“oÚ–yࠃ宔íͳ婒ëξ绖ܜ†ÚŒpΉv®ofZ->V0FW.?a5Jj=KŽPIJB{DAe2>X'<¾Šr¬t`¬s_ÒfЕvÊ›Ο}̘yÌœuÈ•|ÈœˆÆ“~Ä”zÁ‘yÁ‘z¿‘vÆ‘v¾w¸‡p¹€f×¢wòÀ|óÅ€òΗñОòÒ¡òΘïÑ¡ïÏ›îÏšëÒ±ìÓ°ïÒªîÔ±îÓ®BD<9„KF‚AA}>>‹IH^VˈtÝœvç¨zë­뱄ð´~ñ²|ç¡o؃S›SFŽFE°sn¡^Z¶iR¡jyqDWˆkŽg:I_2JaAVw\…sQe„]yhGhuMr‘q–V2R•w‘ ”¦@)EqCRņyϼ¼È«§Ü¯“O=›\Pȵ¶T/FT)>¦k`e2?m9>f4>ŒUM]*3a*:—VKšSJ¼`CÖyQØ}WÚXÞƒ`á‡^àŠgàg܆eárÝo݈`Ü‹kÜoÙtÝ‘ràœtã™jä”læžyðÀ•ç ‡å¤ˆÕ‹j΄rΉvY/FX.>a6DX/C_3@v>CŒPHF>}ABd/8X&<­z®ub¶|`Õ_Ì”lÏšuÏšuÌšxË›~Ç•}Æ“vɘxÓ|Á“wÆ‘tÆ“{Ât¿Œv¸‰o·ƒoÚ¦tðÂzóʈðÑ òÓ›óÑšòÓ¤ïЙíÏ îÒ¤íѪìÕ®ìÓ«îÔ¬íѪm5=q78x<<ƒCB~?@‰HAœZMшkÛ {é®ꬆí¯yï³…ð±të¤qÜ€N”NH•UZ±vx¦^V¼‚…—_kZ,G_5KtIa_9TsNiQ2TkHhˆd‹‡c€tOn`=aŽn˜ƒn‰w‘}Wi×®µu‘ؼ·åϼ¢eI¤fYµƒqU-=V+>V,?‰PH]*7b.:n=>{B=a+4_/>…FC‘NF¶`IÎwWØ]Ú„aÜ|R߃XÞ‡câŒháiâ”k²]=­YAÎqFÖ|MÐyOÕuNÏqGËjEËnOß|K؉g“C8»jN¼lTÛ’u½|fT/JW-AX,?W-;b8Fh3>x<:ROk2=zC@\&8›e`²̓ZÙ‘\ÍoÍšuΚuÍœ}É•yÇ•{Æ”vÂ’}À’yÅ”vÀŽuÀrÂ’t‘y¶‡sµiÞªsñÆ…óΔóÓ¤òÔ¢ðÑðÑ™ïÐðÑŸïÒ¥îÓ§íÕ±îÔ®íÔ¯ðÙªj:Eo:@z<;|A@z?D‘YT«fWÐŽoàž}ë«uì¬xî±{ñ¶{ò´†é¡jÒ…aŸTQË—‹™NG«e`ĉ‚†Sd}Tq]7LkCW\9RnF`{T`=[¡±ƒcŒ|XuŒjŠ‚^}•u’aB^|RnÝ‘eÛ„jîàÕÙ¼Ÿ©j^´thÀŸsW/=_-7V3Bi58_,9i39i68p>Cx=@d.Bw8:‘VQ¬[CÇpRÒwTÖzPÖ€W܃`݇`á…fânà’sÙbØ[ÖsWÓnLØvWß|XÝe×zZÚ}nå€å›‘Ý…vÔ‹uÜŠnÖŒj\0FV3I`7CV-Fa2=zFIk7?‚LLRIe0@Ža]X+;…PP¿ŠÔˆVÙŽ`Ì—|ÐœvΘtÉ—uÇ•xÉ—|Á”}ÓÀ‘•¾‘~À’xÀ’|»v´„n³ƒvä±yôÌôÓ˜òÒ£ñјðÐñÑšñÓ¢ïÒ¤îÒ¦ðÔ¯ïÖ§îÕ¬ñÕ©ðÔªh8Dp7<{@@€A>x:?ŠSP¤bRΊnárꮌë±sì°rðµzï³pä¡}Ç}vÇ–ŽŽHD›QMÆ…±gX”cla1MnASO&8P'D|Piw]€`Ec…›V3T†l’Šk’€^z\7YƒbŒ¢ƒšç”cÌsYßÐÃ[NÉŒyÙ¼¤P-C[9Kc5CW,=\-8s<=a.;i58t?CHGd0;‚D?‡RI‹GA¶gKÍtUÌuQÔ|SØ~TÚ„fÛ‹jãkâ’sãmÜ‚ZØ€\Þ‚Xày]ç…kê†î¦‡ï±”قwÕxÜŒiš[JY.GX.?e4@Z):d5<c/9xE@|=:–QKl3;YQ^*9€N]ËŸÖ’fÕZÌ—vÌœyΛsÊœ{Ì–rÌœƒÊ–uÄ•zÆ—w¾“½Ž}ÕxÂs¼|´ƒn¸{[çµ€öÑóÕ¦òÔŸñÐòÕ§ïÕ®ïÕ©ïÕ°ðÖ«ïÔ«îÔ­îРïÒ¥ðÒ¡g6Bo8;s34s69q7:ŽUH¡ZL͉pæ¢tæ©xë²{ì²zï¶{í³Œç¤‰ÕŠp–OFGF¨my´kf¸pa\2KuOai6D]6KY8U\0N^8T|¢Œn“k?fz\‚gJd„i‰†r¡ŽmœÉŸ£Ñ¢Ì…mÇŸ‰Î…fõÕ›W3J\:Nc;Jd8@[/=e8Dc2?b3>l9>h6A~LI_4F‘VS‰OH}EE±`D¾nNÇrPÐwPÐ`ÓdØeÞ‡bÞ‹kä“pÜ‹i܆aÔ]×|TÞƒaæ„bçŽ|ê“ëuä…pÔ•‚Ü—yʆmW*@U/FV-A_0C\,=b-4f17…E=w=C‘RL€DC’^Yh8CuFTΆ֡ؓfÊšvÌžyÊ›zÍ›xÈ–xË›|Èš}Ä•ƒÁ—yÀ‘yÀ“~»~Ás¾Œr°„r°{cí¿}öÖ£öÖ¢óÔ¡ñÑ›òÖ¨òÖ¨ðÕ¨ñÖ®ñÖ§ñОîÏ›îÍ”ðË‘ðΙc3?g5>p::o9=q69Ÿ]LšUKÏ„dܘsçª|í³‚î´ƒðµxò´|æžlÕT˜REEQѦ©¦`Y«nl_1N‘q|Y+?X2N‚g„[0NnOv±¶Ô}Vu›‘¸z™a>[cCh–ˆª©xp•w‰®¡¾’Þ§k穈m9FY5L\4Gf6Ag4:X-Bj58c4@r=Cf9CvBEq?B_/>„QRˆRMw@C T>¶eIºeEÃnLÊvZÔ{WØ‚`׃cÛ‡hÞrÞŽqÛ…hÛ‚]×VÒ~WËuVËv[ÍrXÐ{\à …Ú{Óor6:U+CQ%<\/Be6CyDEk7=o9>WIˆEB•]Qt>=‘UGl6Bj;IÒ«˜Ú¡„Õ”iÊ›tÅ™tÍœ€Ë™vÈ—uÇ–vÎvƘÁ”|Řy¼x»w¹{·‹y¬}l°wdìÃ…÷Ú©÷Ø£ôÕŸðÕ©ôÖ§ôÙ«òÙ´ðÒ£îΗîÍ”íÌ—ìÐœðРðÏš_2Bg1Ag1:e/9}?>°iP¨fZ΃iÛ“ié£nê²€í²zð³ð²xé¥yׂU—VO†?H¹–£abƒT^g:UrŒ]1DE"A|_~iA]O0\¶¸ß”vbHb™…§€`„€[wŠµ¥qvŒoŠi‚––÷Äw¿{]S.DZ4HX->g7<b1:Z0?h;Eb2Ad8Gk8@l8Bw9<p=Ct<@LGi6?ŽI=¦XAµfJ»iIÈsXÕ~^Õ^Ù]Ü‹iÚŒrÛˆmÚŠlÚˆiÙˆfâ•ná–|àœ~ãž„äž„Ý”rÙp¿{_‡LHW0CO'@X2Cm<Dj<@c7<n8BŠNASOŽXRxA=‹NEn19Z.=ÓªÚ¢}ËmɘsËžzËšyŘ{È™{È•yÊ™‚ׄ¾”xÁ“|¼{¹‹x·‹xµ…m§{j¨udîÆŒõÚ¬õÚ¤òÕ£óÙ²ò×­õÙªñÓŸðÑžïÑ¥ñÔ¢ðÓ ðÒ¥òÔ¨óÒŸ[/?c-:b2Ca2B‘RE©hW¯fUÑ‚]Ü”jë¨vì°ƒê°wð²î¯zæ¡{Öˆ`ŸXI†BG¤nt¥g_sAT‹ct‡byV,CQ+M„`{R.J_7\ª¦ËrUvq’¡˜»’y›{Z€kLn±€—±‹|Uc¶|xÍ k^8LY2L`5G^5G`0>i7A\5Gg6?e0:`.=^,;k9<n7<i6>i7@j;Bm6=†I>:2£WC²bG¾jPÐ{[Ô\Ö†eØ‹pÙ‰gÚŽlà‘qâœ{Ý–säž~䥌é­äžx䢄ޕ{Ó•sV&9„I@W0IY1E]6In<Df3=t?Ck7A˜`YŠOJMB}DE•XRq9>[,BÕ®‘Ü¥zÌ›|Ë ~ÇœyÉœƒÈ–yÁ–|țŖ€Æ˜y¿”{Å”¼”ˆ½x²Š€´‰q¥{k¤ugîÇ‘õÛ¬÷Ú£óÖ¤óÕ¥òÔ¥ôÔŸòÓ¥ñÖ§óÔ¦ðÒ£ñÏ—ñΑòСó͘\2@d7C[-?U0D’XP¬gT©eUІcÞ“jê¦zë²zé°vì°…ð³|è£rÖ€STHIF¡dZ”[\`8IW0LzQ_e:LO1R€Wp\:TiCe ’´gAW_=Y”…³””|¢v[Œ±’ŸË••hD_ŸkktCRg7JW/E\3G\1El;Ek9AZ/Bk9BW(7m=@^.=`/>n8;v:9h7>l8<u@>D?u99u4.–K=±[=ÁnPÓ|WÖ~Y׉kÚwÛ“|â›zâ{穉壇穈奋樊अړyÇŠuS';r>FS3HT/J\4Ip>A\,;m7;`/:™aT‹NN„I@‡OHŽSCŽYUZ+F×®•ÙwÈ•|ˢ˛vÅšƒÅ–xÄ•|Ä“v“yĘ~Å•uÀ”z¹Žz´Ž|²‡x­…t¡{l¬rðÏœõܯ÷Ø óÔ¢òÓ óÖ§óÕ¢óÖ¢òÔ óÐðÍ—òΘï̘óÍ™ïÆŽ],?d5A^1B\->yCD¤aL¿rSÒ†`ß–mç§uê¯{í°wí²}ï­~é lÖ…X™NE|BF˜\Yb:Ic8JQ1Hesb8O[0Ki@[S.GD!J¢´‹i‹mGh…k–i‡š‡ª‰q™’s°Šš†Se–k`qERZ8L[0D[0CV/Dj;D{BDV-?€F@a2=`2@[,:]-7h6@c2:d2;m<?wECg7@OAe0>d)1ƒ??§\HÅtTÉtUÐ}aÑ‚kÞŽlÜ’oÞ“táŸ~奊簗䥄妌àš}Õ“v¶mRW*>Y3M_<PX9Sa5FQPg7Bh7Ba0>Ÿh^‹MK…HC‹LA‘XJ’YV\,CÚ­˜Ú¢€Æ–ÕzƘ}Ä™€Á—ƒÄ™„Á—€¼”€Å˜x¿–w»w´{µŒ€´‰x©užvj¾}ôÕžõÝ®÷ÖžñÑ“òÔŸõצõئôÔŸòÑŸóÎóÊ‘îÇ꾌â¨{¶qFZ+?].@W+<T*?k4AŸ_L§_LÐ_Þšxè¦vè«{ꬃî²wð±wé£sÒ€WI@|FT¶¯ ‚I)IŒ^lmARh=Pc9G^8LN+BO+M¦¤Ç›‹¨d@YgDh•y˜dŒš’¶Žz¥®Ÿ¼¢…©®©dpN+DX.E[2FX2G{DE‹QHU);„SL\.=g5@_0;e5?b0@h3?t=?q?CoAGk;C}GG‚GBs>?v@>C=<3•QD¥`K«j`Æy`Ñ‹sÕuÜ”wâŸ|å¢~ݘ{Þ–uÖŽnÅ‚g£YDR-<\4EX3N];Q]4IsCGg8Dg5?i:E™`[’]X‡PM†NK–_SVG]1GÚ°™Ò•k³}f²}gµƒj¼Œx¾‘~¼‘}¾“€Å”z¿“}¼xµ}µ‹y¯‰x«ƒv§wŸqfد~õ×£÷Ú¨÷ÖœöÕ›õÓžöÔ—õЗóÏ“òÏ‘ïÄŒëµw͇Ku:8Y+9R+>f5@`3BV)<R*?i47”YI˜PDÉ|[Ü–mæ¦zé¬zéªmç«{ï¯|çiÉyQ^fëÜÉs<U´ž©M+EsK`g?UnEVrIUc8KM*FU+Qœ’²š‚“rJ`oJloHa‚f‚‡sž{Y‰¢²’}›}M^µ¨¼‡c~J*GQ'>W+@‘PMƒNLR)=}DAW-=]2Cb0>^0=[-=a.:m=Aj5:m9Dj5:s;;•NA›PB½mVÈzgÔ…h׆jÖuЉpÜ’uÙqßœ|Þ ßž€Û {ߥ‰âª‰ß°“Þ»Ÿ¼œ{QZU9NW1IY4H\5FoAM^4Bc7EJI—\QRIUO„LL™ZQ‡ICj:DÓ©“Á…c°z^©mWªsf±z]±i±t²ƒn²†vÅ’w½wµŽ{´Šu¬‡r©p¢zoŸtoçÂŒö×¢õÓ˜öÒ™îÏ—ôÒõÑ•ôÏ–ôʊ渇ΙtƒHCQ#7Q*=d2>u<<l>He5@_-BY.?a.<„H@ŠIAÇaÚ‘jæ¤xì®éªtë®}ï¯wæ›iˉ}ྈzFO]0EwIRP-Hh?RsFRe:Ia8KrKX]7MX-Ke›©¢©^9TY8\œ‰° ¾„h”†kƒ’p‘’w”nIZµ—‰k‘O3Ha6DEIq>D^3D‰QK\-@Z+?c4B_/:a1Ae4Ad6Bu@Gu@Dg4Ai6C—TI¬`OÌxYσeÎ~_Í~_Ò„cÈ„mчiØoÛ“vÙ”pÖ–yבrוy× ‡ß¯‡çÀ›êâëɤáÅ«”uˆW?U_;Lf<MV1G`<Pk=GYT~GL‰UXˆQR›\R†SStEQÓ’k¼~`´r®p®rb®wc«o`¦n]¤p`£sa°~n¯m¬}p­†z®…yª„|žyožspðÉ’öÖ›õÍöΑóÑ™óÑšöÑšôɆ鿈ک~›_K\,B\/Bo=D’TG‹NK“cd€JMo=@a1@i37{B@v=:±hOØŽfæ¥è©véªz詃ï­æ¬œÝ™g‰EE}K]©‹‘R'>I)?R+D}N^b9MV/HlHTQgnBXN(C—‡ª[}ˆoŸ¶¤¶b?[|]‹‰k“‹sŒvOx¬—¼­…Ž’ytZ=Q^0Ax@Fh;HV2GŒTNX.=Y+<X,:h7?`0?`/:]*7m>Dm8Bc3=h5>ŽUT·hMÊz_Ë|_Ì~aÏ{`΄lЊqÚ‰fÜŠaÙr׊j׉i×rÚ—yà£{ã³å¿çÄèÆŸêÈ¡ï̪êΪ•w†M-=M)>Q'9k:CIE~GIƒLITQ‹QI~ED†MPÖ•gµ~gÉq½…j½aµ€q³xc«tf£iZ fW™g[žj_¡sn™i_ob›iX—lcžj^ïÄŠöÑóȉõЖôÒ—ñИöÑ—ëÁ•Ù«|QFZ.<g1;q;?PI‘WN•YL§„…¥}t“\TzGG„MKv8<g.6VE׈_ä¢z諃ì¯}é©|ñ³‚ê¢rÓ…]ŽPS¤hZv:?M';M'>Y0>_3H“v”G!;j9PiyK[L%>S)K£“³wšƒ\™Ž¬qTm‚f‹k—”«‹m“Žjˆ ~Ÿc4Ež’Œg7C‚CBa3CS&<‹OD\+9`/>U';f6?_3GX-Bg9Ci=GKJk6Aa0<…FC°gO½qSË{bÌz[Ð}^Ï}aÓƒcÙ‰pØŠmÚ‰mØŒnØŽlØ“yÞ™zܧŒå¹è¾›çÁœè˜êÇ¥ï̦ïÌ©òÏ°æÏ®iJQF 9a4:ŽVP€FGxGF„JG€EDLT‘_`Ö’h¼†w¼Žx¿s¿‹o¶„r¼„n±~o«ub«p] gZŸcV•aYYT—`UªqW”^QˆOO쿆öÏ’öËôÓœóÍ“òÌìËá©vSE`/<†OJ†JJHF•XNSJ“VI§‚¨Œ‹§ƒ‚žso‘_RƒEBc*5–UFÓˆeä£yç¦xê©tê­zî®~ê iÎ}a¹~t¨toR.IV/DL$:I#BŸ}œl‰L,KŽo“uFZ€Xo]5Oa;TyMghDd™†ž]8UsPvz_zu—uœ—¤¢†£’c\vJ^tMbŽdqw?C]3?Q+B…OJ^3Dh8DZ2Dj<JmJP]6I`3?`4@v>EyDFc7@ŠPK¨fVÄtWÆvZÐ`ÏaÊ‚eÚŠhØlÜ“uÙnÙˆlÙ’tÛ•xÝŸ€á«„崌鿙徚èÁ—éžíÉ ðͪò̦òÒ®óÖµ‘ya6=e9G{GLyGHŒQG{CCk4:®zmЕuÍ’sÈ”y¿“wÀ‹mÂw¸Œ}¼‹{·„r¯{k¨xm¡na qd‘ZU®t`Æ‚Y™bRVPïĆ÷Ò˜öÐ’øÖœöÒ›òÍ–Ø›js<?])5PHŽSF‹NE“XO[K“RG•WL¢~¨’”®”˜©„~žom‡FA[(:—UIÓ‡hç§~ì¯vé©vë­{ï¯oè¤vÒŒwåÀ›‚DDj@UW-EP%5L'@j?PM'>zUgm?RlE[c<[‡i‘koM&F–Š­`9UkEbb@\yX}‡kˆš‚ ’|¡“¨K#C»§ŸP*Iµ˜‚d2GR.FN)BŠOJf3Bd9KR1Fb2@g=Ib1>]4Ii4At?F©cI`0>‹WR±o\ÅqWÑ„^Ì~]É{dÖ‹o܆aÙŽiØŒn؆dÙ‰gÚ‘lÜœ{à¢䧃⭉åµæº˜å¼—澘ëÅŸðÉ¢ðÍ£óÏ«õÓ±ô×·ž‰_6MtAIsBC~JFw>@\(=ÈŽ{ΔuÏšyÄ—}Á‘z¿s¾Žwºx´‡xµ…p³…u¯|p§xp¤yqŸnf¸yVÈ„X¨j[ʈ\ôË“õÕž÷Ô ÷Ö óˉ뿃¥gOW*>ŽPG—YL–XK”RL¨gW_N˜\Sœ\I›ut¬Œ«——«•¬‡{”ZNa,9—PBÒ‰hç¦pì¬xì®wë«oåŸsã”tµuiÑÅËE <Z/@f;Cg8LP[O/CtGSV2HjAT]5JS+Ab=RR/RƒjvO)EpQjiGe|`€‚d†‘v“›…œˆ«›…œrDOÀ­±c9Ml?LU+BX4N{KRf9M\5IW3I\8LsDFhAW`6DvIO‚NU®iXe7Hs>E¸wgÈ{_Êz^Áx`׈kÜi׈lÛŽmÚŠfÝgÚlÝ•wàœxÝŸ}⩇ã¢~å­‚ä±æ¸Œë»‘ë¿‘ìÆï̦ñΤñÓ·óÖºôؽ‹fi}C>r;;~FA‚HHP(CÙª‡Ë‘pÅ“vÈ–t¼‘r¾tÀnÁz»Šw½‰u¾Šu±‚o´‚n¨o¨yiµzYȆY»uNÞ¨uôÓŸöÕš÷Ô—øÕœíňןiB?zDGŸ^Nž_S›ZL­jU´€z¡`M“QL¢`UsEQœ~„¬“—¸¡›º–…¡tna.9•SC׌`è¥zðµ‡ë±€í°~ï±wë jÝŒZ¤y~g6>P(@P&;b6AV,8W0Bk8FS.BQ*G‰c{sJbK(A\6@O&BY;X|VfQ.HnFalJpx—’u–˜}—¢”·¦š±¤‚†j<;a8[ͺÁM&8M$7w@Eh8Ab0@S)@^2E~MO_0<T'6„IE˜\OÈ}_…A?c/5¥^M¶eMÎeÖ…aÙ‡fØŠmÖ†dÚŠjÜ‹eÙpÜmß”oàšpážuà¡~ã§å±‹â®å¶‰çº’ì“ì˜îÆœòÌŸôѧòÓ³õÙ½ôÜ»o@IY(6yA@n?AR%AÙ®ŽÄŒmÃnÆjÄ“qÀtÄq¿x»~¾Žy¸‰u·‡x­n®€q¯}oÁ„`ÎŽ[Ä|Uì¿z÷ןõÔöÕœõҙ꿂½{TzGKš^Q™SK¢aQ¢cV³t^¬jSŸ[N `P¢f[S*<Šbm®˜“¼¦ ½Ÿ§wa-8ŽKEÖŽgé§|í°|î±~ë¯zí³zèŸ^߉`²ƒ‚~‡E6O&:[/A‰e{Q)>Q1G^1C[/J“p…^:LX&3J!=‰aP-GoEe„a€nMd{XhDeˆoŽl‹‹p”­—¨™{‘D#@ ˆ©ÝÙÓH%<P'>q;@~DFa-<U+;Y3G‚RSa:J[+;u:=±`IÌxX—TDV'8 faÊvTׂcÕƒ`Ùc݉lÛ‹eÙŒeÞhØŒkÙqà™uà›uߟ}â¡~ä¤{å­á¬‡å²Žæ·è¾™êÀ–íÅšñÊ¡ñвñѳõÖ³õáÈÜË´P%7€lsi6<U%?ÌœzÀŽvÄ”uÄ‘vÀ’y¿’y¾Žm¿Œrºˆs½ŽzºŒz¸ˆv²…r®}j­x_¿ƒbÏŽWÑYòljøÙ¡÷ÖšøÓ•öÑ’â­rŽLD˜WLž^Wž`R¢bTµqY¯hW˜XM^T¬hU¦i_H 5j=K©”–¼©¥¾£•©‡}T':€?;ØŒdè¦zì²yì®|ì¶~ò°zí¥sÝŒZЦ„g:KT0FM':[2F`:NY3HT-?T,Ba9Q‘v“`:Ng7IK"6L">h‡{W{sMpaŠlˆn‹uVx€a~¢”¹¬›¬c3K]3OŸszàÖÍN+EP&9}CA„OEc4AU.@Y3GvACb.:_2?l6>ª`N¾pI¡ZG`,;¦bSÉqOÙ\Ø€bÛ‡_Ü…_܇eÝ‘mÜ‹eÝkÝ’kà‘iÞ˜tà›uÝœyà¢}ä§㬄届沉溗ê½ìÄšïʨñдñÒ´óÖ¾õÜÄ÷ß»k:;e/9^,7a+7ÕšrËjÉ–xÊ‘lÇ”w¿lÀ{¼Šr¹‚³‰v¶‰t°„u®q«zh±yfËlä¬sî¾{õÏ—õÙ¥øÖšøÓ˜òÈ~ÍŠOšXQ¤`M›VO¬fT²oV²mZž^NšYN©gY£kdŸi_R):a3F¢Š‹Â«¤½¤—¦ƒ{O&;†G<ÙŒ`é¨xñ³ë±sî±}ñµví¦jß‹a©~{M)Ce7MX-Cc:Jb;HV.C]7LS-J€ZnˆbxH"=qJT]/DQ%;[7Ra<Va8ImMfwUquXwwX}€a„¦—°–s…“v’U-D…Z`¸¿I"9U.FŽUM–_Xe4@[5I`0Al;JX*;b-9ˆLE¼jL¹nX¬_C]*7¢bWÒ|ZÙƒZ×`݇\߉[Ü‹aÞŠaÝjÙmÝ’sÛlÞ•oàœqß™pày⧃᪅䯒嶎å·æ¼—éžð̪óЬðÓ·ïÒµôÛÄ÷ÜÂÞË´U#2W$2c37Ùž€ÃŽqÅ”wÇ—vÄ’pÁŽp“v¾Žqµ‹x²„p·„o³‚l­}g°zcÀ‚bê¹~õÈøË“û×÷ØŸ÷ך÷Ò‘å´q©cJ¡`L£]M©bO¬k]½uWªdN˜[PŸ]R«o_›_WžldK 6\,@¥‡…º§¦À«¥†{Q -?9Ö‰^ê¦oëµ|í²wé´ƒñ¶wë¦jߌf«L+>P%:iCO_6GY*<T(8M%8P-RŸ€–‚YtJ-Bc@OlEX]4K[1FT4MR+Ge=RzYu‰kfEbuPiš€Ÿ¤–®ŒrŠ\Œ¥Š¡h<OY/@M%9‰LG|A=h9An;C_3Db5G]5GvAA™SEÄpRÍ}_²dFd09­iVÙ~XØ‚bÝ…]ÞˆdÝŠeÛ…]ÙŠqÞŠ`Þ‹gÚpÜ‘hÝ“lß”kÞyà¡~å¥|Þ§ˆã­†ã±Œç¹’ç¾—êÁ›í̳ñвðÒ¶ñÕ»óÝÇ÷ÛÂôÞµL2S#3ŽH>ÔiÆ”yÈ“x¿r¼‹sÆ‘sÁp¾sºˆm»‰m²€n©|s©ye°zcÜ©vùÔ›øÕ õΑøÕœøÙ¡öÔ™òÈÙX¤]I¡\K _P°fO»sX¸u\œZNšZL«k[£dW›`X”_^G3U%:›z»§¢È­¡­Š}[)3z88Ù‡Wë§wí²|ì°|í±xîµ}í¦pÛ‰Y­rV.Ie>LN$9T*9[,?]3JR-H”yœl>Ie7IK'@S*@vJ\b<HL$;e=MT)?j?YZ4X˜”f?c|a‰œ†¢±¡¹›x¡Œ[o­›¡vQGO(@e4>f5@c05f2@o;Dj?Id09_-=v=BÁrQÏ^È|^®[DyCA«iX×zP׃g܈gÞˆiߊcÚ‰dÛ‡`ÝŒfß…^ÝŒhÝnÚ~à–rßœxàwß¡᧊㯎ä³å¸Žå½æÃ¥íɬðϱïÏ´ïÓ»ïÖÁöÚ¾öß¼­scF0¬kYÏ‹dÏŸzÈ•uÁrÃn½ŽqÁqÀp¶‰t²ƒn³„m­€r¬zhµw[꾆÷Ù¡ùÔ—÷Ñ•öÖ øؤùÒè´}ÂuK¬_H XE¥_L²lW¹oP§cQŸ^PŸ`P¦g[škh•aZˆVVJ!4U(>™|…·¤¤Âª¡­…h4:|>BÚˆZê§rì®{é²yæ­pë±vâŸrØ‘lžs„g?PU-BQ-CU,9[)9V,JwReO1So†xSeZ/BW.?d:HP(<P*Ab9JS'D†cwS-Gb=[“zš”|£¥Ž ‰_~–}“¥”³¬—°~[ƒ”sgrA=[/;\0AuCFg4@n=Cb1<v<@MBËyQÉ|[Í{WŠGA‡QP´iNÙ‰fׄcÛ…dÞˆ`àŒbÙrÞ‰^Û‰lÛ‰gÛ‹dÛjÝ“mÝ‘nÞž~Þ›{à¡á¦ƒã©Œâ°‹ã´‹æ¿™åÀ¢ëÅ©îͲîεïѺïÔ¼ò×¾õÛÁâÍ·C4ǃfËŠeÄ•v½yÑu½r½v½ŠgÀn·Šuµ…q³„r¨}n­z`¼†zïÅŠøØ£ôÍ‹÷ÓúÚ¨øØ›õÌŠÛ˜_»tU¹gG­`JªbJ¸kK³nU¢_Oœ^P¤hX¢fX’]S‘XNƒQUG1P%<”pwº§¦Æ­§²’ƒc/7|;>ÕƒWí©xç¯~å¯~è±}çŸkÛŒb¶~xNXW)=\8IV*=_7FV1DQ/AZ4G„\muFYS,>mKY[6GV-A_8OU1?V-HŽq”d>WL*Ik™œ˜„Ÿ•n‘U(;V+0L':\39j;=¥€Œ®–® ’`.9f8Dm<Cg6D‚FC¦\IÑ[Ï|[ÓVŠOP˜ZMÁpPÖƒc׆fÝ„XÞˆ_áŒfÞŠaÛ‹e܆\Þ‰\܇aÞiÞŒdÜ•pÞ™xá›|àžzá¡~㩉߬‚ä´äº˜å½šèÅ¥íÊ®îË­ðѵïÓºîÕÂóØÁð×­E6Á‚\ÁŠlÅ“oÅ’r½Žu¼y¹ˆr¸Šq¾s½Œn¯‚o°ƒp«~n°}bÈ€\ôÊŽøØ™öˆ÷Ñ”ùÜ­úÔ‘ìºwÌ}SÆ{V±jN«`M°hT´oSª_Fœ[L\R£i]˜\R›cX‰WV^ZG4O(=‰en¸¡žÅ¯¥±˜vEBs;>ÕƒZë¨mí±xî°uì²tì²zé¤pÖ…`¥mrk8Ef<PV/C[.FZ2GU-Dd=PQ,FjBP`8L^<PT.EgBTT,@R(>pH^W,KnFVB!;g@]‚`…Œz Œv’‹p•ž…”U/GO&9m6<V->m@LvLPq?E¦}bi7?c2<i9B–SJ½kJÍzVÏbÏ€Zr4=£e]ÏbÚƒYÛ„YÝ…\ÞŽoÝŠeàŽiÚ…^Ý„^ÞŒkÜŒcÛˆ`ßfß’rÝ•tÞ|Þ›|Ý£‚ᩎெᭈ乕㿙çŪìÉ«îжëϺðÒ·ñÕ¿òÖ»õÚ·Z(9ÃxRÁ‹qÄ•sÄ”w¿“yÃnºŠp¼u¶‰n½y³‰t¶…l¬o´…mljjî½úÒŽõˆøБüÚõÏá fÇyW¼pRµjJ [L«bM­gN’UL—ZL©i[¡ga”_Y”ZS[Z’abM!7N">€Y\¯˜™½©Ÿ±™wGI}>?Òƒ^è nì±~è®ê³ƒíµ‰ç¢fÚ’kÇ|vGRd=NW.BO)EY4Peq]5ET,CkCWc9M\0?X/AL(?{WxX->a=VzUq[6Sb†V;L|f“†r£“„¥kDhr’“m‰W-=L#8tBFc6>s>Ei4<b19^2B^+6~@=ŸXK¹lSÍxSÍgÁvTb3D§fVÔ„a؆^ÝhÜiÝeâdà‹cÛŠdÚx܈_àˆYßbáhÛ“lÚ’lâ–gàšmÝŸ~à§xÞ£~ᬈⳌ仗çÁŸêÉ­ëË«îеðѸðÕ¶îÓ¿ò×¼Ò­£ÌƒXÄq¾•¼’u½‘w¾‘wÄ”sÀt½Œr¼q²…s¯†v´…k»…g̈^ÒZæ³pë»yöÕ£ùØ›ôÊ…Ú“\¾rUºoP²cH¡\L¨fTœZMŒNG§eS¤dWš^W•[P“ZT“a^“`XO(9F5rHY­™–À¬œ³š‹ˆ]\|?@Ó‚V驅ê¯~節ð°té¤oÒ‡hÉ‹zŒ\eZ2FU1KwP\c6HR.EW3DW1Ke7Kc9Oc>QkCVc:Qc?Te8LW3Hc8OY2Gy]xgCi^>Uz`x™‘±h<[hHoœ}˜¥–¶H$8j:@S(<e6C[-6e9D]1@c.;ˆGCµjQÊwUÏ‚^Êz[¤VB†NK·qYׂbÚ‰dà‹_ÞláißhÜŒkߌ\Û†_ÙŠbÞ‹aÜnÜŽrÞ‘mÞ–mÝ—và›sÝ›xÞ á£}á°ƒáµäµŒæÁ¥éǧêɳíйðÓ»òÓ¸ïÕÀñÕ¿ñÔ®Ô‘`²k¤raªwb¶‚m½ˆj¾sÁ”}¼’z»‘v´Šs¶ŒvÁˆhÉŽkÑ”oɉa˃Rç³tûÛ¤ûÙ˜ñÁvÓ…Y¼rS±^E£\M¦`Q¥_JŒKC›WJ¦fT›_UŽXRVI“^Z‘caKIN&9K#4zMX©“•¹§¨²š‘…YXA<ЀQç¡oì¯í¯zë±uð²{ë¦sØcÈ’‚Ž_j]1BN(=Z0>Y2DR+<\6IoJ_rGXZ<Vƒ_gV3GW+<\/AR*HtQg`6GT-L’{£…h“d<WF#@hDWb;T„f‡rIa“{‘d1>k;DR'5`09Z'5Z,:_05k7?–SGÂnKÌvSÌ}]ËxXi7IšWKÓ‚[ÚˆeÙ‡dÝuß‹gàgÝqßdáhàiÝŠ_Û‰`ÝŠ`Þbßeß•oß•qàœuÞ›qà¡~ᩃ᫆⮅縒佛èÀ ëÉ®éÉ­ñÔÀòÕ¼ðÕ¿ïÓ¼ôڹͅU–[G’VHWGcM¦p[­w`±†x¸ˆp·†n¸u¸‹pÇŽnÓœfÑ’^ˇV͈XîÑúÛ£ûÕ’ç¯aÅxN¶fJ•SG›UGªfOMB•TI¤lfŸ`W—bZYXœkh’^YˆVUu>?N(:N#5^1C±›™Æ±«¾¦˜—oju<=Ï}Oãmé­wê®yæ¯{ñ³wì§màa¢kk‚R]Q)@V*;[-=U+<W/Je>MV/Eg?SZ6Ke8F`6DX,AO$5Q(>X.?iR‚‰u ~[œˆ™\:T€bˆnF]c;Sƒj„€Xrl>G^0<U&9d6?\1>X)8V(8g26ŠKGµeFÈxVÆsRÉvN¨]Ae9MªeVÕWÚˆh؆_ÞqÝ‘nã’bÞŠjàdá‹ZáŒhÛˆ^Ú…[Þˆ^ÚŒgÞŠ]Ý“làšvÞšvÝšsßžpâ£xà©„á«~ß±Žå»˜åÀçÆ©ëÏ·îжðÓ¸ðÓ¸ñØÁ÷Û¾ÊwSIaXF@†GBŠQ@”]M“]Q–cTnb¢sf¸‡qÊ–}Ô¢rÉ’iŇ_Õ˜hõÑ’ýÞ¦öÉÛW¶jP›S@ŠMCŸZP˜SIŒMEaXž`Tš_[“_W•`\˜jfa]~JGm59N%9E0^4I®•È¯¡¿¨˜£|mz=;ÊuRãnç¬~ê±yë®{ñ´í¨tÞ“`¢ps‹YcM%?f;LQ0JP(AU/Ci>KU4Kc9HW3Gj@Mg:Qg<IP%:X1@\4JW2@L'C]š‚ž¯¥¾hC]‡g†¤„˜d4=\/=g4@iAHU*6W/:T&2T(8\+7q:=—P@ÄqOÇx\É€`ÅwNU$6’REÌ~\܈d؆d݇cÜŽkÞbâhÞiß‘pãŒ`áˆ^ÝŒ_܆YÚŠeÝnÛŽgÞiß“pà—mÝ™rÜ›pÝ¡zᤃߨƒá¯ä¹•ä¿¢êħëË®ìηðвîÔ¾ñÔ¸ô׿æ͹‰MH˜\L™]L“XL‡PL…JH|B?s=@p?EsAA‰XN´ySËŒcÜ®sÙš_߬rùÕ™üÙ˜ì°\ÁrI“NB|=>”NA’MF‹KCžbZ¥nc‘UP[T‘ZRžf``^‰WWk;@k7@_/:n<Ek7A¬“‘dz©Ç¯ ¦ˆyw<<ÈvTàŸwæ­zè±vè¯xï·tí­qЉc¦{xm=ML&>S);V.@]2E]4G_8MW2Jd;T[4Hi=Qf=I^/CjBSR+?X1@`<R]1JO,J†j§¦Ë‹q~~YjY{tM_P&;e7=[+:g=PT+>S'4X)7h.8ˆF?¶hKËxNÆvUÌ{U{6/g3>°mYÓƒZÝ‹_߆`ÚˆhÞaÞ‹_á‰aߎiânÞkàŽ_ß‹cÛ…Y݆[ÜŠ[Û…YÛeÜ’nÛ•oà™mÞ™nàŸwà¢zঃⴑ㳉世åĪéǬí̳ìϾîÔ¿ïÔÂõÙ¾ôدNC™`K¥hZ¡fU–^S‰QEƒIFp;Ae38Z+5U+6xBI߯€ïÆ‚à©]î½}úÓúωܖS—RAs9;‹JF’WLƒIG–YS¡lh™^N“[Y\S”YS li]ZxJIs>>g2<”\V‡PKŠ\`¦ˆ~Ƴ¨Í·§ª‹xBAÈsHãŸyë®}ê°}é²{ð¼„ë®qÀoX·‡‚zKYR%7W0GgAPX0FR(<\2@X7Oc<NkET^:G_7MiBUR/GL&:V+>`5GsL]S)>I(I„k‚ž“ºsšŠbƒ¡}ˆV0EW0?V+5R&6R%8U0?Z*?PE™YHÅrNÇtUÉwPC6W'9žXMÓ€YØ„WÙ†[ÝŠeÜ‹f݆]áŠ]áiãfß“oâ‹\áfÛŠ_ÝjÚh݈\ÞŠcÝŠ^ÚŽfß’eà”kܘqÝ›yáŸ|ߥyß©ƒå´ãº•çÀ¡çÆ­éɳêÍ»îÒ¾ñÔ»òÕ½öÙ¸ŸeX™^M¤k[¦o\ŸgZ”_U“]VGEtEM_/9O'=DDòÆ‹÷ÍÝ™[óÇyüÔé¶q”P?m57{@>‰LC†HH‹QP¥i_šcWˆPO‰TJŒTJ˜f`¢ttˆYWzIJr@Dk6>[VZR–ljª…­¡Æ·¥¯•‰€FAÂsSàœpê¬tî±tê°ñ¸wé­l¨cN¶{jƒQ_Z1EU,C[3BV-=X+=Y5IW1DV0DR*=pGYX0Be=RU-CW0He9JN$8j?MZ6MhCVn@U^:Sh}w˜T/E`1>T)<S(<U)4K!5`1>r<?’SK¸gHÉ|\ÊsK‡>0P!3˜WEÎ~WÔ~Vׄ^Ù†c߉aÓ†eߎaÞ‹\á‹cÝdÝqÝ‹_Þ’oàŠ\ÞŠcß‹hÝ‹^ÝhØŒiÚ‰^àdà•aÛ”iátÞŸ|ߣ‡Þ§{㱒㶗㽠æçéȳë͹ëѽòÔÀñѸöÙ¿Ôµ§’WM j`©m[ŸdUšaR˜\QŽUJyF@k:?`,9ˆILèµ|öÉ{ðÀuõÆ„é®g—YCg3;j5=LFz?CŠNJœbVš^R‹RO„OO‚LF’ZW qr•fa†UWSRo:BrBK…QMŸqnŸro©Š„Å® È¯ž±–††PFÀqRá›oç²xè¬që´‚î¸vî­v®cS®rm_3Eb9JT3GZ1C^6HV,@a8HQ)@X4LcF]iBQT,CrK[g=R\6GV/GŠf}^8TnB^a:UoOf’x’l?S[4@p?HV+=R);X-;O)7S%,a1:MA¶hK·iJ°eIO!,a-7¯cEÃtOÑxQØ„WØ„WÛ‰]܈WÛkÞ‹aÜŠeÞŒhÞcß‹aÞiáfÝ‘jߌeà‹cߌ\ÞbÞ‰^Ú‹gÝiÛ‘iÜ’eÜ™tÞŸwߤ}à¥|ᧀ௑⸖你æÅ­ìÍ°ëϸîÒ½ïÔ»óÙÃïÕ®‹MB™f^¡hYŸeUg\—bU˜bWˆUU†NJ‰VOœ\Káµ}úÕ—ôÅ}×’Z›]Lw@?m5;ƒLGE@ˆI@™aV£lcŒZX}KP†NLŒ[W kg¡mj^^‹XXtDGwGIg6<uBF”f]‘fiœ~€»¥›Ç³¡±˜‹YN¿qJášjê­z것ê´ð·|íªq¿vZ—gcR+AU.;]=Sb6Eh;ER+>_3HoFXY/Dc;P`=QU0GyVrvP`O(<V,G|VpO*>~`hW3JjIhsNx£–º\6GfE\O*FX/6Q)9Z.:\*4}B;–Q=i29O&4j6>ŸT@²cGÇuSÍxWÔ~U؃ZÔZ؆_ÜŒ^Û…[ß’kÞŽoߊaáeãŽfß‘dà’já“jÝ’ißbÜŒgÞŠXÛeÝŒaÝ‹\ÝŒ]Ü“kà˜lÞ™rÞ¡|ृã©z⯋ඕ忢åìçÇ­êϸìѽðÒ¿ñÖÁðÕ°ŒRI’ZP›eYžl\—g\šg^–dYŽ^Y–a]™\S bZà«wñƈؖTRH‚LFz>C~F>…GB„LKžb^¤ph“_W€NMu>A‡LM˜`XŸoe›id’a`yDGp><sCDl>Fb2:~W[†]dšz~¹¨¢Æ¯¢µ™„œi_ÀpJÞ›jæ¬vì²|îµ€ó·}îªlÎoNVN'@S+@T1?a9Mo?Q\6J`6F[1Ha3IW/HuZsR/G€]€‘u’sJ^I)@ƒaqM#2pLs•x_:X–€£‚buo~T2GQ*>V-?\1>Z)7X(6U'5l7>NC¤YDµeMÃqSÐwQÎyRÑ€UÒ~TÕ|QÔ‚\׆bÚŠgÛˆ[݈_Ý…YÝ‹dàŠbß`ÝŒgß’nâ•kÞgÝŽdÞaÞŒb܉[á`Þ‘iÜdÞ’ià™oàžàŸuà£â©„â±äº˜äº¥ä¿£çÅ«é̳ìлïÕÀñÖÀñؼ»†y‡RJ’b[–eUžgZ¢qc—cbœf\­t`¬lX³nVÂ{W¹xT”UKPG’UI–[PPF„FE—aZœga“^TJF{IMwBH™c^œpn¤rq“cc‰Z`vGLq=Aq>A_0;d:Di<E~PUmv¸¥ É´¥¹¢‘¡rc¶oTÝ™né®~í´{ïµ|ó¸}è«xʆbwIRY1GL&7U0BV/=oDWkK\b5L„cU.@]2H‰k„P-Gh>Xb=W‘v”M(Fm‹ew@8tI]U.?gGb™y‹sRhiCSL$6Z7ER&5a,/t95–N<¦XA¹mOÂnLÈv[Ï|ZÑzTÑ|WÒUÕ‚VÖRÕ‚XÚƒV܈a݈]܈cÛˆ\àŒ_á`Þ‹aÜŽkÝ‘màgÝbÞ‘làeàcÛdàeá’iÜjÛ“dÞ•pà›vÜ›yà¡~ृ஑ఇⶕ⽡çĦåÈ­éεïÓ»îÕ¿ð×¾ßƯ‚HCŒ]T’bXšfZ¡r_lZ¤te­v^¯nS¹pX¬kX¨eQš^V¡eT¦dO–VJ‰JGSRœlo]XKL‡RN~JK‰RI§zv§{yŸnh’e`}EHq=Ag6>i8Aa3>`4:`1:g@H‡_hκ°âË°ÝƯ«r¶rYÞšsí°}î³xïµ}÷¹}ç¥wƒQZh?K]3IV*?O(6_4FjAOb8Pg?Ua@NO)@S+LnƒQ/DmF^sC_Œ­[>QhGd—‚¤V0Fg<N¢’¤D"?oQl‰h“]7FP%;W/Ad08r1/’L;¸gK½sSÌtLÄqGÆvSÏ}PÒ}T׃YÔ|OØP؃^Ô]Ù„XÛ„TÛ‡]݇XÝeàˆ\áeß‹\áeáŽcá‹gá’jÞ“oß’nÝ‘já“dÞ“hà”gÛ’hß–fÞ•pà—jÝœsÞ¢€ä©~䭌ౕà³ãºšäÀ§æȯéʳëθéÏÁåͶìÓ¯{@BˆYQ˜h^›kYjb pb¯w`´s[¸rS»tT·qX­iS®gNÁxW®jQ™XPš[R–_WˆV]{CD}JE„F?‚JEœg`©zu¢vt™mv†WUqBFf8@j>Cf39}A<a6?a4=d6EjpÜÄ®ã˷ݦ˩ˆ»vWÞ–gì­tí±xì°zð¸‚æ¤nÁ…zh;QS+9N&?R,=X1Cd5Hg9NqFTX.LuGbP.HwMaU2PZuZ/GsOap’V3S†emV-9P*DoFYWwyNj˜|¦–•K%5S%3s30–NA§W>¹jDÂkHÉrHÊyWÉuMÏ{MÒZÓ}SÓ|Q؃SÙ€S؃XÚ‚X܆\Þˆ[Þ†[Û…^äWÝŠ^߉[Þoáná‘jà“jÝià’ià’hà•já–kâ“mß`ß—lä›uáštãvÞŸqà¦yߦ~ⱈà³ä»¥ã¾¡äÅ®èÉ´ëϸëмìÒ»ïÔ³†LG†UQŒYK—f^™g\¥sg±t\¿~_Â~b¸uYºqS½oQË~WÇwP¯iS`^œg]Š[[SV…MPƒNI…MF—bY±zk¬ysh`†W[r??c1<d26e39GIœZH\1:`18Z,<xQ`ÙÁ±ÞȲÙÁ«È§ŽºxZÜšpëªxì³}붆ñ·é®}…W[a8KR%<X.@M(BZ1AnDQg?PtL]_8Ig<U†i|\.@P&;vHVU+FtJ`]aa:L’|œZ2GI&@ƒ[kg?IO(?uScsKc‹cXl8BšQ@¦X@«dI¿iGÊtGÈuUÎ}XÑ|TÔWÎ~_Ó€VÓYׂU×^ØRÛƒZÜ„Vá†YÞŽiÜ…W݈]àŠ`ÞŒeÞŽgà‘jßiÞ‘kâgá’fàfà’fá“là˜oá“`Þ–lß–uãŸwàžqâ yߧ†à£yà©‹à­Šâ·ä½äÂ¥çȯêÊ®íνêнïÔº»ŠƒŠ]^’]IŒWM—eV£n\¯ua΄]É|WÅzSÃxWÔˆZÓ‰`ÄsM£`O•YLˆQO{JQ‰\WŒYU‡QP[Uªsj²‚z«yŽ_arFEa19^0=_-6tFF—\P¬dL \ No newline at end of file
diff --git a/Imaging/MANIFEST b/Imaging/MANIFEST
new file mode 100644
index 0000000..7ab93ae
--- /dev/null
+++ b/Imaging/MANIFEST
@@ -0,0 +1,275 @@
+README
+CHANGES
+CONTENTS
+MANIFEST
+BUILDME
+setup.py
+selftest.py
+doctest.py
+libImaging/Imaging.h
+libImaging/ImDib.h
+libImaging/ImPlatform.h
+libImaging/Quant.h
+libImaging/QuantHash.h
+libImaging/QuantHeap.h
+libImaging/QuantDefines.h
+libImaging/QuantTypes.h
+libImaging/Access.c
+libImaging/Antialias.c
+libImaging/Bands.c
+libImaging/Blend.c
+libImaging/Chops.c
+libImaging/Convert.c
+libImaging/ConvertYCbCr.c
+libImaging/Copy.c
+libImaging/Crc32.c
+libImaging/Crop.c
+libImaging/Dib.c
+libImaging/Draw.c
+libImaging/Effects.c
+libImaging/Except.c
+libImaging/File.c
+libImaging/Fill.c
+libImaging/Filter.c
+libImaging/Geometry.c
+libImaging/GetBBox.c
+libImaging/Histo.c
+libImaging/Matrix.c
+libImaging/ModeFilter.c
+libImaging/Negative.c
+libImaging/Offset.c
+libImaging/Pack.c
+libImaging/Palette.c
+libImaging/Paste.c
+libImaging/Point.c
+libImaging/Quant.c
+libImaging/QuantHash.c
+libImaging/QuantHeap.c
+libImaging/RankFilter.c
+libImaging/Storage.c
+libImaging/Unpack.c
+libImaging/UnpackYCC.c
+libImaging/Bit.h
+libImaging/Gif.h
+libImaging/Jpeg.h
+libImaging/Lzw.h
+libImaging/Raw.h
+libImaging/Zip.h
+libImaging/BitDecode.c
+libImaging/EpsEncode.c
+libImaging/FliDecode.c
+libImaging/GifDecode.c
+libImaging/GifEncode.c
+libImaging/HexDecode.c
+libImaging/JpegDecode.c
+libImaging/JpegEncode.c
+libImaging/LzwDecode.c
+libImaging/MspDecode.c
+libImaging/PackDecode.c
+libImaging/PcdDecode.c
+libImaging/PcxEncode.c
+libImaging/PcxDecode.c
+libImaging/RawDecode.c
+libImaging/RawEncode.c
+libImaging/SunRleDecode.c
+libImaging/TgaRleDecode.c
+libImaging/XbmDecode.c
+libImaging/XbmEncode.c
+libImaging/ZipDecode.c
+libImaging/ZipEncode.c
+_imaging.c
+decode.c
+encode.c
+display.c
+map.c
+outline.c
+path.c
+_imagingtk.c
+_imagingft.c
+_imagingmath.c
+PIL.pth
+PIL/__init__.py
+PIL/ArgImagePlugin.py
+PIL/BdfFontFile.py
+PIL/BmpImagePlugin.py
+PIL/BufrStubImagePlugin.py
+PIL/ContainerIO.py
+PIL/CurImagePlugin.py
+PIL/DcxImagePlugin.py
+PIL/EpsImagePlugin.py
+PIL/ExifTags.py
+PIL/FitsStubImagePlugin.py
+PIL/FliImagePlugin.py
+PIL/FontFile.py
+PIL/FpxImagePlugin.py
+PIL/GbrImagePlugin.py
+PIL/GdImageFile.py
+PIL/GifImagePlugin.py
+PIL/GimpGradientFile.py
+PIL/GimpPaletteFile.py
+PIL/GribStubImagePlugin.py
+PIL/Hdf5StubImagePlugin.py
+PIL/IcoImagePlugin.py
+PIL/IcnsImagePlugin.py
+PIL/Image.py
+PIL/ImageChops.py
+PIL/ImageColor.py
+PIL/ImageDraw.py
+PIL/ImageDraw2.py
+PIL/ImageEnhance.py
+PIL/ImageFile.py
+PIL/ImageFileIO.py
+PIL/ImageFilter.py
+PIL/ImageFont.py
+PIL/ImageGL.py
+PIL/ImageGrab.py
+PIL/ImageMath.py
+PIL/ImageMode.py
+PIL/ImageOps.py
+PIL/ImagePalette.py
+PIL/ImagePath.py
+PIL/ImageQt.py
+PIL/ImageSequence.py
+PIL/ImageStat.py
+PIL/ImageTk.py
+PIL/ImageTransform.py
+PIL/ImageWin.py
+PIL/ImImagePlugin.py
+PIL/ImtImagePlugin.py
+PIL/IptcImagePlugin.py
+PIL/JpegImagePlugin.py
+PIL/McIdasImagePlugin.py
+PIL/MicImagePlugin.py
+PIL/MpegImagePlugin.py
+PIL/MspImagePlugin.py
+PIL/OleFileIO.py
+PIL/PaletteFile.py
+PIL/PalmImagePlugin.py
+PIL/PcdImagePlugin.py
+PIL/PcfFontFile.py
+PIL/PcxImagePlugin.py
+PIL/PdfImagePlugin.py
+PIL/PixarImagePlugin.py
+PIL/PngImagePlugin.py
+PIL/PpmImagePlugin.py
+PIL/PsdImagePlugin.py
+PIL/PSDraw.py
+PIL/SgiImagePlugin.py
+PIL/SpiderImagePlugin.py
+PIL/SunImagePlugin.py
+PIL/TarIO.py
+PIL/TgaImagePlugin.py
+PIL/TiffImagePlugin.py
+PIL/TiffTags.py
+PIL/WalImageFile.py
+PIL/WmfImagePlugin.py
+PIL/XbmImagePlugin.py
+PIL/XpmImagePlugin.py
+PIL/XVThumbImagePlugin.py
+Docs/index.html
+Docs/effbot.css
+Docs/pythondoc-PIL.ArgImagePlugin.html
+Docs/pythondoc-PIL.BdfFontFile.html
+Docs/pythondoc-PIL.BmpImagePlugin.html
+Docs/pythondoc-PIL.BufrStubImagePlugin.html
+Docs/pythondoc-PIL.ContainerIO.html
+Docs/pythondoc-PIL.CurImagePlugin.html
+Docs/pythondoc-PIL.DcxImagePlugin.html
+Docs/pythondoc-PIL.EpsImagePlugin.html
+Docs/pythondoc-PIL.ExifTags.html
+Docs/pythondoc-PIL.FitsStubImagePlugin.html
+Docs/pythondoc-PIL.FliImagePlugin.html
+Docs/pythondoc-PIL.FontFile.html
+Docs/pythondoc-PIL.FpxImagePlugin.html
+Docs/pythondoc-PIL.GbrImagePlugin.html
+Docs/pythondoc-PIL.GdImageFile.html
+Docs/pythondoc-PIL.GifImagePlugin.html
+Docs/pythondoc-PIL.GimpGradientFile.html
+Docs/pythondoc-PIL.GimpPaletteFile.html
+Docs/pythondoc-PIL.GribStubImagePlugin.html
+Docs/pythondoc-PIL.Hdf5StubImagePlugin.html
+Docs/pythondoc-PIL.IcoImagePlugin.html
+Docs/pythondoc-PIL.IcnsImagePlugin.html
+Docs/pythondoc-PIL.Image.html
+Docs/pythondoc-PIL.ImageChops.html
+Docs/pythondoc-PIL.ImageColor.html
+Docs/pythondoc-PIL.ImageDraw.html
+Docs/pythondoc-PIL.ImageEnhance.html
+Docs/pythondoc-PIL.ImageFile.html
+Docs/pythondoc-PIL.ImageFileIO.html
+Docs/pythondoc-PIL.ImageFilter.html
+Docs/pythondoc-PIL.ImageFont.html
+Docs/pythondoc-PIL.ImageGL.html
+Docs/pythondoc-PIL.ImageGrab.html
+Docs/pythondoc-PIL.ImageOps.html
+Docs/pythondoc-PIL.ImagePalette.html
+Docs/pythondoc-PIL.ImagePath.html
+Docs/pythondoc-PIL.ImageSequence.html
+Docs/pythondoc-PIL.ImageStat.html
+Docs/pythondoc-PIL.ImageTk.html
+Docs/pythondoc-PIL.ImageTransform.html
+Docs/pythondoc-PIL.ImageWin.html
+Docs/pythondoc-PIL.ImImagePlugin.html
+Docs/pythondoc-PIL.ImtImagePlugin.html
+Docs/pythondoc-PIL.IptcImagePlugin.html
+Docs/pythondoc-PIL.JpegImagePlugin.html
+Docs/pythondoc-PIL.McIdasImagePlugin.html
+Docs/pythondoc-PIL.MicImagePlugin.html
+Docs/pythondoc-PIL.MpegImagePlugin.html
+Docs/pythondoc-PIL.MspImagePlugin.html
+Docs/pythondoc-PIL.OleFileIO.html
+Docs/pythondoc-PIL.PaletteFile.html
+Docs/pythondoc-PIL.PalmImagePlugin.html
+Docs/pythondoc-PIL.PcdImagePlugin.html
+Docs/pythondoc-PIL.PcfFontFile.html
+Docs/pythondoc-PIL.PcxImagePlugin.html
+Docs/pythondoc-PIL.PdfImagePlugin.html
+Docs/pythondoc-PIL.PixarImagePlugin.html
+Docs/pythondoc-PIL.PngImagePlugin.html
+Docs/pythondoc-PIL.PpmImagePlugin.html
+Docs/pythondoc-PIL.PsdImagePlugin.html
+Docs/pythondoc-PIL.PSDraw.html
+Docs/pythondoc-PIL.SgiImagePlugin.html
+Docs/pythondoc-PIL.SpiderImagePlugin.html
+Docs/pythondoc-PIL.SunImagePlugin.html
+Docs/pythondoc-PIL.TarIO.html
+Docs/pythondoc-PIL.TgaImagePlugin.html
+Docs/pythondoc-PIL.TiffImagePlugin.html
+Docs/pythondoc-PIL.TiffTags.html
+Docs/pythondoc-PIL.WalImageFile.html
+Docs/pythondoc-PIL.WmfImagePlugin.html
+Docs/pythondoc-PIL.XbmImagePlugin.html
+Docs/pythondoc-PIL.XpmImagePlugin.html
+Docs/pythondoc-PIL.XVThumbImagePlugin.html
+Scripts/pilconvert.py
+Scripts/pildriver.py
+Scripts/pilfile.py
+Scripts/pilfont.py
+Scripts/pilprint.py
+Images/lena.gif
+Images/lena.ppm
+Images/lena.jpg
+Images/courB08.bdf
+Images/courB08.pbm
+Images/courB08.pil
+Sane/README
+Sane/CHANGES
+Sane/setup.py
+Sane/sanedoc.txt
+Sane/_sane.c
+Sane/sane.py
+Sane/demo_numarray.py
+Sane/demo_pil.py
+Scripts/README
+Scripts/enhancer.py
+Scripts/explode.py
+Scripts/gifmaker.py
+Scripts/image2py.py
+Scripts/painter.py
+Scripts/player.py
+Scripts/viewer.py
+Scripts/thresholder.py
+Tk/tkImaging.c
+Tk/install.txt
+Tk/booster.txt
+Tk/pilbitmap.txt
diff --git a/Imaging/PIL.pth b/Imaging/PIL.pth
new file mode 100644
index 0000000..b338169
--- /dev/null
+++ b/Imaging/PIL.pth
@@ -0,0 +1 @@
+PIL
diff --git a/Imaging/PIL/ArgImagePlugin.py b/Imaging/PIL/ArgImagePlugin.py
new file mode 100644
index 0000000..48582d9
--- /dev/null
+++ b/Imaging/PIL/ArgImagePlugin.py
@@ -0,0 +1,498 @@
+#
+# THIS IS WORK IN PROGRESS
+#
+# The Python Imaging Library.
+# $Id: ArgImagePlugin.py 2309 2005-03-02 15:06:34Z fredrik $
+#
+# ARG animation support code
+#
+# history:
+# 1996-12-30 fl Created
+# 1996-01-06 fl Added safe scripting environment
+# 1996-01-10 fl Added JHDR, UHDR and sYNC support
+# 2005-03-02 fl Removed AAPP and ARUN support
+#
+# Copyright (c) Secret Labs AB 1997.
+# Copyright (c) Fredrik Lundh 1996-97.
+#
+# See the README file for information on usage and redistribution.
+#
+
+__version__ = "0.4"
+
+import marshal, string
+
+import Image, ImageFile, ImagePalette
+
+from PngImagePlugin import i16, i32, ChunkStream, _MODES
+
+MAGIC = "\212ARG\r\n\032\n"
+
+# --------------------------------------------------------------------
+# ARG parser
+
+class ArgStream(ChunkStream):
+ "Parser callbacks for ARG data"
+
+ def __init__(self, fp):
+
+ ChunkStream.__init__(self, fp)
+
+ self.eof = 0
+
+ self.im = None
+ self.palette = None
+
+ self.__reset()
+
+ def __reset(self):
+
+ # reset decoder state (called on init and sync)
+
+ self.count = 0
+ self.id = None
+ self.action = ("NONE",)
+
+ self.images = {}
+ self.names = {}
+
+
+ def chunk_AHDR(self, offset, bytes):
+ "AHDR -- animation header"
+
+ # assertions
+ if self.count != 0:
+ raise SyntaxError, "misplaced AHDR chunk"
+
+ s = self.fp.read(bytes)
+ self.size = i32(s), i32(s[4:])
+ try:
+ self.mode, self.rawmode = _MODES[(ord(s[8]), ord(s[9]))]
+ except:
+ raise SyntaxError, "unknown ARG mode"
+
+ if Image.DEBUG:
+ print "AHDR size", self.size
+ print "AHDR mode", self.mode, self.rawmode
+
+ return s
+
+ def chunk_AFRM(self, offset, bytes):
+ "AFRM -- next frame follows"
+
+ # assertions
+ if self.count != 0:
+ raise SyntaxError, "misplaced AFRM chunk"
+
+ self.show = 1
+ self.id = 0
+ self.count = 1
+ self.repair = None
+
+ s = self.fp.read(bytes)
+ if len(s) >= 2:
+ self.id = i16(s)
+ if len(s) >= 4:
+ self.count = i16(s[2:4])
+ if len(s) >= 6:
+ self.repair = i16(s[4:6])
+ else:
+ self.repair = None
+
+ if Image.DEBUG:
+ print "AFRM", self.id, self.count
+
+ return s
+
+ def chunk_ADEF(self, offset, bytes):
+ "ADEF -- store image"
+
+ # assertions
+ if self.count != 0:
+ raise SyntaxError, "misplaced ADEF chunk"
+
+ self.show = 0
+ self.id = 0
+ self.count = 1
+ self.repair = None
+
+ s = self.fp.read(bytes)
+ if len(s) >= 2:
+ self.id = i16(s)
+ if len(s) >= 4:
+ self.count = i16(s[2:4])
+
+ if Image.DEBUG:
+ print "ADEF", self.id, self.count
+
+ return s
+
+ def chunk_NAME(self, offset, bytes):
+ "NAME -- name the current image"
+
+ # assertions
+ if self.count == 0:
+ raise SyntaxError, "misplaced NAME chunk"
+
+ name = self.fp.read(bytes)
+ self.names[self.id] = name
+
+ return name
+
+ def chunk_AEND(self, offset, bytes):
+ "AEND -- end of animation"
+
+ if Image.DEBUG:
+ print "AEND"
+
+ self.eof = 1
+
+ raise EOFError, "end of ARG file"
+
+ def __getmodesize(self, s, full=1):
+
+ size = i32(s), i32(s[4:])
+
+ try:
+ mode, rawmode = _MODES[(ord(s[8]), ord(s[9]))]
+ except:
+ raise SyntaxError, "unknown image mode"
+
+ if full:
+ if ord(s[12]):
+ pass # interlace not yet supported
+ if ord(s[11]):
+ raise SyntaxError, "unknown filter category"
+
+ return size, mode, rawmode
+
+ def chunk_PAST(self, offset, bytes):
+ "PAST -- paste one image into another"
+
+ # assertions
+ if self.count == 0:
+ raise SyntaxError, "misplaced PAST chunk"
+
+ if self.repair is not None:
+ # we must repair the target image before we
+ # start pasting
+
+ # brute force; a better solution would be to
+ # update only the dirty rectangles in images[id].
+ # note that if images[id] doesn't exist, it must
+ # be created
+
+ self.images[self.id] = self.images[self.repair].copy()
+ self.repair = None
+
+ s = self.fp.read(bytes)
+ im = self.images[i16(s)]
+ x, y = i32(s[2:6]), i32(s[6:10])
+ bbox = x, y, im.size[0]+x, im.size[1]+y
+
+ if im.mode in ["RGBA"]:
+ # paste with transparency
+ # FIXME: should handle P+transparency as well
+ self.images[self.id].paste(im, bbox, im)
+ else:
+ # paste without transparency
+ self.images[self.id].paste(im, bbox)
+
+ self.action = ("PAST",)
+ self.__store()
+
+ return s
+
+ def chunk_BLNK(self, offset, bytes):
+ "BLNK -- create blank image"
+
+ # assertions
+ if self.count == 0:
+ raise SyntaxError, "misplaced BLNK chunk"
+
+ s = self.fp.read(bytes)
+ size, mode, rawmode = self.__getmodesize(s, 0)
+
+ # store image (FIXME: handle colour)
+ self.action = ("BLNK",)
+ self.im = Image.core.fill(mode, size, 0)
+ self.__store()
+
+ return s
+
+ def chunk_IHDR(self, offset, bytes):
+ "IHDR -- full image follows"
+
+ # assertions
+ if self.count == 0:
+ raise SyntaxError, "misplaced IHDR chunk"
+
+ # image header
+ s = self.fp.read(bytes)
+ size, mode, rawmode = self.__getmodesize(s)
+
+ # decode and store image
+ self.action = ("IHDR",)
+ self.im = Image.core.new(mode, size)
+ self.decoder = Image.core.zip_decoder(rawmode)
+ self.decoder.setimage(self.im, (0,0) + size)
+ self.data = ""
+
+ return s
+
+ def chunk_DHDR(self, offset, bytes):
+ "DHDR -- delta image follows"
+
+ # assertions
+ if self.count == 0:
+ raise SyntaxError, "misplaced DHDR chunk"
+
+ s = self.fp.read(bytes)
+
+ size, mode, rawmode = self.__getmodesize(s)
+
+ # delta header
+ diff = ord(s[13])
+ offs = i32(s[14:18]), i32(s[18:22])
+
+ bbox = offs + (offs[0]+size[0], offs[1]+size[1])
+
+ if Image.DEBUG:
+ print "DHDR", diff, bbox
+
+ # FIXME: decode and apply image
+ self.action = ("DHDR", diff, bbox)
+
+ # setup decoder
+ self.im = Image.core.new(mode, size)
+
+ self.decoder = Image.core.zip_decoder(rawmode)
+ self.decoder.setimage(self.im, (0,0) + size)
+
+ self.data = ""
+
+ return s
+
+ def chunk_JHDR(self, offset, bytes):
+ "JHDR -- JPEG image follows"
+
+ # assertions
+ if self.count == 0:
+ raise SyntaxError, "misplaced JHDR chunk"
+
+ # image header
+ s = self.fp.read(bytes)
+ size, mode, rawmode = self.__getmodesize(s, 0)
+
+ # decode and store image
+ self.action = ("JHDR",)
+ self.im = Image.core.new(mode, size)
+ self.decoder = Image.core.jpeg_decoder(rawmode)
+ self.decoder.setimage(self.im, (0,0) + size)
+ self.data = ""
+
+ return s
+
+ def chunk_UHDR(self, offset, bytes):
+ "UHDR -- uncompressed image data follows (EXPERIMENTAL)"
+
+ # assertions
+ if self.count == 0:
+ raise SyntaxError, "misplaced UHDR chunk"
+
+ # image header
+ s = self.fp.read(bytes)
+ size, mode, rawmode = self.__getmodesize(s, 0)
+
+ # decode and store image
+ self.action = ("UHDR",)
+ self.im = Image.core.new(mode, size)
+ self.decoder = Image.core.raw_decoder(rawmode)
+ self.decoder.setimage(self.im, (0,0) + size)
+ self.data = ""
+
+ return s
+
+ def chunk_IDAT(self, offset, bytes):
+ "IDAT -- image data block"
+
+ # pass compressed chunks through the decoder
+ s = self.fp.read(bytes)
+ self.data = self.data + s
+ n, e = self.decoder.decode(self.data)
+ if n < 0:
+ # end of image
+ if e < 0:
+ raise IOError, "decoder error %d" % e
+ else:
+ self.data = self.data[n:]
+
+ return s
+
+ def chunk_DEND(self, offset, bytes):
+ return self.chunk_IEND(offset, bytes)
+
+ def chunk_JEND(self, offset, bytes):
+ return self.chunk_IEND(offset, bytes)
+
+ def chunk_UEND(self, offset, bytes):
+ return self.chunk_IEND(offset, bytes)
+
+ def chunk_IEND(self, offset, bytes):
+ "IEND -- end of image"
+
+ # we now have a new image. carry out the operation
+ # defined by the image header.
+
+ # won't need these anymore
+ del self.decoder
+ del self.data
+
+ self.__store()
+
+ return self.fp.read(bytes)
+
+ def __store(self):
+
+ # apply operation
+ cid = self.action[0]
+
+ if cid in ["BLNK", "IHDR", "JHDR", "UHDR"]:
+ # store
+ self.images[self.id] = self.im
+
+ elif cid == "DHDR":
+ # paste
+ cid, mode, bbox = self.action
+ im0 = self.images[self.id]
+ im1 = self.im
+ if mode == 0:
+ im1 = im1.chop_add_modulo(im0.crop(bbox))
+ im0.paste(im1, bbox)
+
+ self.count = self.count - 1
+
+ if self.count == 0 and self.show:
+ self.im = self.images[self.id]
+ raise EOFError # end of this frame
+
+ def chunk_PLTE(self, offset, bytes):
+ "PLTE -- palette data"
+
+ s = self.fp.read(bytes)
+ if self.mode == "P":
+ self.palette = ImagePalette.raw("RGB", s)
+ return s
+
+ def chunk_sYNC(self, offset, bytes):
+ "SYNC -- reset decoder"
+
+ if self.count != 0:
+ raise SyntaxError, "misplaced sYNC chunk"
+
+ s = self.fp.read(bytes)
+ self.__reset()
+ return s
+
+
+# --------------------------------------------------------------------
+# ARG reader
+
+def _accept(prefix):
+ return prefix[:8] == MAGIC
+
+##
+# Image plugin for the experimental Animated Raster Graphics format.
+
+class ArgImageFile(ImageFile.ImageFile):
+
+ format = "ARG"
+ format_description = "Animated raster graphics"
+
+ def _open(self):
+
+ if self.fp.read(8) != MAGIC:
+ raise SyntaxError, "not an ARG file"
+
+ self.arg = ArgStream(self.fp)
+
+ # read and process the first chunk (AHDR)
+
+ cid, offset, bytes = self.arg.read()
+
+ if cid != "AHDR":
+ raise SyntaxError, "expected an AHDR chunk"
+
+ s = self.arg.call(cid, offset, bytes)
+
+ self.arg.crc(cid, s)
+
+ # image characteristics
+ self.mode = self.arg.mode
+ self.size = self.arg.size
+
+ def load(self):
+
+ if self.arg.im is None:
+ self.seek(0)
+
+ # image data
+ self.im = self.arg.im
+ self.palette = self.arg.palette
+
+ # set things up for further processing
+ Image.Image.load(self)
+
+ def seek(self, frame):
+
+ if self.arg.eof:
+ raise EOFError, "end of animation"
+
+ self.fp = self.arg.fp
+
+ while 1:
+
+ #
+ # process chunks
+
+ cid, offset, bytes = self.arg.read()
+
+ if self.arg.eof:
+ raise EOFError, "end of animation"
+
+ try:
+ s = self.arg.call(cid, offset, bytes)
+ except EOFError:
+ break
+
+ except "glurk": # AttributeError
+ if Image.DEBUG:
+ print cid, bytes, "(unknown)"
+ s = self.fp.read(bytes)
+
+ self.arg.crc(cid, s)
+
+ self.fp.read(4) # ship extra CRC
+
+ def tell(self):
+ return 0
+
+ def verify(self):
+ "Verify ARG file"
+
+ # back up to first chunk
+ self.fp.seek(8)
+
+ self.arg.verify(self)
+ self.arg.close()
+
+ self.fp = None
+
+#
+# --------------------------------------------------------------------
+
+Image.register_open("ARG", ArgImageFile, _accept)
+
+Image.register_extension("ARG", ".arg")
+
+Image.register_mime("ARG", "video/x-arg")
diff --git a/Imaging/PIL/BdfFontFile.py b/Imaging/PIL/BdfFontFile.py
new file mode 100644
index 0000000..9297a18
--- /dev/null
+++ b/Imaging/PIL/BdfFontFile.py
@@ -0,0 +1,133 @@
+#
+# The Python Imaging Library
+# $Id: BdfFontFile.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# bitmap distribution font (bdf) file parser
+#
+# history:
+# 1996-05-16 fl created (as bdf2pil)
+# 1997-08-25 fl converted to FontFile driver
+# 2001-05-25 fl removed bogus __init__ call
+# 2002-11-20 fl robustification (from Kevin Cazabon, Dmitry Vasiliev)
+# 2003-04-22 fl more robustification (from Graham Dumpleton)
+#
+# Copyright (c) 1997-2003 by Secret Labs AB.
+# Copyright (c) 1997-2003 by Fredrik Lundh.
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image
+import FontFile
+
+import string
+
+# --------------------------------------------------------------------
+# parse X Bitmap Distribution Format (BDF)
+# --------------------------------------------------------------------
+
+bdf_slant = {
+ "R": "Roman",
+ "I": "Italic",
+ "O": "Oblique",
+ "RI": "Reverse Italic",
+ "RO": "Reverse Oblique",
+ "OT": "Other"
+}
+
+bdf_spacing = {
+ "P": "Proportional",
+ "M": "Monospaced",
+ "C": "Cell"
+}
+
+def bdf_char(f):
+
+ # skip to STARTCHAR
+ while 1:
+ s = f.readline()
+ if not s:
+ return None
+ if s[:9] == "STARTCHAR":
+ break
+ id = string.strip(s[9:])
+
+ # load symbol properties
+ props = {}
+ while 1:
+ s = f.readline()
+ if not s or s[:6] == "BITMAP":
+ break
+ i = string.find(s, " ")
+ props[s[:i]] = s[i+1:-1]
+
+ # load bitmap
+ bitmap = []
+ while 1:
+ s = f.readline()
+ if not s or s[:7] == "ENDCHAR":
+ break
+ bitmap.append(s[:-1])
+ bitmap = string.join(bitmap, "")
+
+ [x, y, l, d] = map(int, string.split(props["BBX"]))
+ [dx, dy] = map(int, string.split(props["DWIDTH"]))
+
+ bbox = (dx, dy), (l, -d-y, x+l, -d), (0, 0, x, y)
+
+ try:
+ im = Image.fromstring("1", (x, y), bitmap, "hex", "1")
+ except ValueError:
+ # deal with zero-width characters
+ im = Image.new("1", (x, y))
+
+ return id, int(props["ENCODING"]), bbox, im
+
+##
+# Font file plugin for the X11 BDF format.
+
+class BdfFontFile(FontFile.FontFile):
+
+ def __init__(self, fp):
+
+ FontFile.FontFile.__init__(self)
+
+ s = fp.readline()
+ if s[:13] != "STARTFONT 2.1":
+ raise SyntaxError, "not a valid BDF file"
+
+ props = {}
+ comments = []
+
+ while 1:
+ s = fp.readline()
+ if not s or s[:13] == "ENDPROPERTIES":
+ break
+ i = string.find(s, " ")
+ props[s[:i]] = s[i+1:-1]
+ if s[:i] in ["COMMENT", "COPYRIGHT"]:
+ if string.find(s, "LogicalFontDescription") < 0:
+ comments.append(s[i+1:-1])
+
+ font = string.split(props["FONT"], "-")
+
+ font[4] = bdf_slant[string.upper(font[4])]
+ font[11] = bdf_spacing[string.upper(font[11])]
+
+ ascent = int(props["FONT_ASCENT"])
+ descent = int(props["FONT_DESCENT"])
+
+ fontname = string.join(font[1:], ";")
+
+ # print "#", fontname
+ # for i in comments:
+ # print "#", i
+
+ font = []
+ while 1:
+ c = bdf_char(fp)
+ if not c:
+ break
+ id, ch, (xy, dst, src), im = c
+ if ch >= 0 and ch < len(self.glyph):
+ self.glyph[ch] = xy, dst, src, im
diff --git a/Imaging/PIL/BmpImagePlugin.py b/Imaging/PIL/BmpImagePlugin.py
new file mode 100644
index 0000000..a939d9b
--- /dev/null
+++ b/Imaging/PIL/BmpImagePlugin.py
@@ -0,0 +1,245 @@
+#
+# The Python Imaging Library.
+# $Id: BmpImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# BMP file handler
+#
+# Windows (and OS/2) native bitmap storage format.
+#
+# history:
+# 1995-09-01 fl Created
+# 1996-04-30 fl Added save
+# 1997-08-27 fl Fixed save of 1-bit images
+# 1998-03-06 fl Load P images as L where possible
+# 1998-07-03 fl Load P images as 1 where possible
+# 1998-12-29 fl Handle small palettes
+# 2002-12-30 fl Fixed load of 1-bit palette images
+# 2003-04-21 fl Fixed load of 1-bit monochrome images
+# 2003-04-23 fl Added limited support for BI_BITFIELDS compression
+#
+# Copyright (c) 1997-2003 by Secret Labs AB
+# Copyright (c) 1995-2003 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+
+__version__ = "0.7"
+
+
+import string
+import Image, ImageFile, ImagePalette
+
+
+#
+# --------------------------------------------------------------------
+# Read BMP file
+
+def i16(c):
+ return ord(c[0]) + (ord(c[1])<<8)
+
+def i32(c):
+ return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
+
+
+BIT2MODE = {
+ # bits => mode, rawmode
+ 1: ("P", "P;1"),
+ 4: ("P", "P;4"),
+ 8: ("P", "P"),
+ 16: ("RGB", "BGR;16"),
+ 24: ("RGB", "BGR"),
+ 32: ("RGB", "BGRX")
+}
+
+def _accept(prefix):
+ return prefix[:2] == "BM"
+
+##
+# Image plugin for the Windows BMP format.
+
+class BmpImageFile(ImageFile.ImageFile):
+
+ format = "BMP"
+ format_description = "Windows Bitmap"
+
+ def _bitmap(self, header = 0, offset = 0):
+
+ if header:
+ self.fp.seek(header)
+
+ read = self.fp.read
+
+ # CORE/INFO
+ s = read(4)
+ s = s + ImageFile._safe_read(self.fp, i32(s)-4)
+
+ if len(s) == 12:
+
+ # OS/2 1.0 CORE
+ bits = i16(s[10:])
+ self.size = i16(s[4:]), i16(s[6:])
+ compression = 0
+ lutsize = 3
+ colors = 0
+
+ elif len(s) in [40, 64]:
+
+ # WIN 3.1 or OS/2 2.0 INFO
+ bits = i16(s[14:])
+ self.size = i32(s[4:]), i32(s[8:])
+ compression = i32(s[16:])
+ lutsize = 4
+ colors = i32(s[32:])
+
+ else:
+ raise IOError("Unsupported BMP header type (%d)" % len(s))
+
+ if not colors:
+ colors = 1 << bits
+
+ # MODE
+ try:
+ self.mode, rawmode = BIT2MODE[bits]
+ except KeyError:
+ raise IOError("Unsupported BMP pixel depth (%d)" % bits)
+
+ if compression == 3:
+ # BI_BITFIELDS compression
+ mask = i32(read(4)), i32(read(4)), i32(read(4))
+ if bits == 32 and mask == (0xff0000, 0x00ff00, 0x0000ff):
+ rawmode = "BGRX"
+ elif bits == 16 and mask == (0x00f800, 0x0007e0, 0x00001f):
+ rawmode = "BGR;16"
+ elif bits == 16 and mask == (0x007c00, 0x0003e0, 0x00001f):
+ rawmode = "BGR;15"
+ else:
+ # print bits, map(hex, mask)
+ raise IOError("Unsupported BMP bitfields layout")
+ elif compression != 0:
+ raise IOError("Unsupported BMP compression (%d)" % compression)
+
+ # LUT
+ if self.mode == "P":
+ palette = []
+ greyscale = 1
+ if colors == 2:
+ indices = (0, 255)
+ else:
+ indices = range(colors)
+ for i in indices:
+ rgb = read(lutsize)[:3]
+ if rgb != chr(i)*3:
+ greyscale = 0
+ palette.append(rgb)
+ if greyscale:
+ if colors == 2:
+ self.mode = rawmode = "1"
+ else:
+ self.mode = rawmode = "L"
+ else:
+ self.mode = "P"
+ self.palette = ImagePalette.raw(
+ "BGR", string.join(palette, "")
+ )
+
+ if not offset:
+ offset = self.fp.tell()
+
+ self.tile = [("raw",
+ (0, 0) + self.size,
+ offset,
+ (rawmode, ((self.size[0]*bits+31)>>3)&(~3), -1))]
+
+ self.info["compression"] = compression
+
+ def _open(self):
+
+ # HEAD
+ s = self.fp.read(14)
+ if s[:2] != "BM":
+ raise SyntaxError("Not a BMP file")
+ offset = i32(s[10:])
+
+ self._bitmap(offset=offset)
+
+
+class DibImageFile(BmpImageFile):
+
+ format = "DIB"
+ format_description = "Windows Bitmap"
+
+ def _open(self):
+ self._bitmap()
+
+#
+# --------------------------------------------------------------------
+# Write BMP file
+
+def o16(i):
+ return chr(i&255) + chr(i>>8&255)
+
+def o32(i):
+ return chr(i&255) + chr(i>>8&255) + chr(i>>16&255) + chr(i>>24&255)
+
+SAVE = {
+ "1": ("1", 1, 2),
+ "L": ("L", 8, 256),
+ "P": ("P", 8, 256),
+ "RGB": ("BGR", 24, 0),
+}
+
+def _save(im, fp, filename, check=0):
+
+ try:
+ rawmode, bits, colors = SAVE[im.mode]
+ except KeyError:
+ raise IOError("cannot write mode %s as BMP" % im.mode)
+
+ if check:
+ return check
+
+ stride = ((im.size[0]*bits+7)/8+3)&(~3)
+ header = 40 # or 64 for OS/2 version 2
+ offset = 14 + header + colors * 4
+ image = stride * im.size[1]
+
+ # bitmap header
+ fp.write("BM" + # file type (magic)
+ o32(offset+image) + # file size
+ o32(0) + # reserved
+ o32(offset)) # image data offset
+
+ # bitmap info header
+ fp.write(o32(header) + # info header size
+ o32(im.size[0]) + # width
+ o32(im.size[1]) + # height
+ o16(1) + # planes
+ o16(bits) + # depth
+ o32(0) + # compression (0=uncompressed)
+ o32(image) + # size of bitmap
+ o32(1) + o32(1) + # resolution
+ o32(colors) + # colors used
+ o32(colors)) # colors important
+
+ fp.write("\000" * (header - 40)) # padding (for OS/2 format)
+
+ if im.mode == "1":
+ for i in (0, 255):
+ fp.write(chr(i) * 4)
+ elif im.mode == "L":
+ for i in range(256):
+ fp.write(chr(i) * 4)
+ elif im.mode == "P":
+ fp.write(im.im.getpalette("RGB", "BGRX"))
+
+ ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, stride, -1))])
+
+#
+# --------------------------------------------------------------------
+# Registry
+
+Image.register_open(BmpImageFile.format, BmpImageFile, _accept)
+Image.register_save(BmpImageFile.format, _save)
+
+Image.register_extension(BmpImageFile.format, ".bmp")
diff --git a/Imaging/PIL/BufrStubImagePlugin.py b/Imaging/PIL/BufrStubImagePlugin.py
new file mode 100644
index 0000000..ee02659
--- /dev/null
+++ b/Imaging/PIL/BufrStubImagePlugin.py
@@ -0,0 +1,68 @@
+#
+# The Python Imaging Library
+# $Id: BufrStubImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# BUFR stub adapter
+#
+# Copyright (c) 1996-2003 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image, ImageFile
+
+_handler = None
+
+##
+# Install application-specific BUFR image handler.
+#
+# @param handler Handler object.
+
+def register_handler(handler):
+ global _handler
+ _handler = handler
+
+# --------------------------------------------------------------------
+# Image adapter
+
+def _accept(prefix):
+ return prefix[:4] == "BUFR" or prefix[:4] == "ZCZC"
+
+class BufrStubImageFile(ImageFile.StubImageFile):
+
+ format = "BUFR"
+ format_description = "BUFR"
+
+ def _open(self):
+
+ offset = self.fp.tell()
+
+ if not _accept(self.fp.read(8)):
+ raise SyntaxError("Not a BUFR file")
+
+ self.fp.seek(offset)
+
+ # make something up
+ self.mode = "F"
+ self.size = 1, 1
+
+ loader = self._load()
+ if loader:
+ loader.open(self)
+
+ def _load(self):
+ return _handler
+
+def _save(im, fp, filename):
+ if _handler is None or not hasattr("_handler", "save"):
+ raise IOError("BUFR save handler not installed")
+ _handler.save(im, fp, filename)
+
+
+# --------------------------------------------------------------------
+# Registry
+
+Image.register_open(BufrStubImageFile.format, BufrStubImageFile, _accept)
+Image.register_save(BufrStubImageFile.format, _save)
+
+Image.register_extension(BufrStubImageFile.format, ".bufr")
diff --git a/Imaging/PIL/ContainerIO.py b/Imaging/PIL/ContainerIO.py
new file mode 100644
index 0000000..7b7283f
--- /dev/null
+++ b/Imaging/PIL/ContainerIO.py
@@ -0,0 +1,116 @@
+#
+# The Python Imaging Library.
+# $Id: ContainerIO.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# a class to read from a container file
+#
+# History:
+# 1995-06-18 fl Created
+# 1995-09-07 fl Added readline(), readlines()
+#
+# Copyright (c) 1997-2001 by Secret Labs AB
+# Copyright (c) 1995 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+##
+# A file object that provides read access to a part of an existing
+# file (for example a TAR file).
+
+class ContainerIO:
+
+ ##
+ # Create file object.
+ #
+ # @param file Existing file.
+ # @param offset Start of region, in bytes.
+ # @param length Size of region, in bytes.
+
+ def __init__(self, file, offset, length):
+ self.fh = file
+ self.pos = 0
+ self.offset = offset
+ self.length = length
+ self.fh.seek(offset)
+
+ ##
+ # Always false.
+
+ def isatty(self):
+ return 0
+
+ ##
+ # Move file pointer.
+ #
+ # @param offset Offset in bytes.
+ # @param mode Starting position. Use 0 for beginning of region, 1
+ # for current offset, and 2 for end of region. You cannot move
+ # the pointer outside the defined region.
+
+ def seek(self, offset, mode = 0):
+ if mode == 1:
+ self.pos = self.pos + offset
+ elif mode == 2:
+ self.pos = self.length + offset
+ else:
+ self.pos = offset
+ # clamp
+ self.pos = max(0, min(self.pos, self.length))
+ self.fh.seek(self.offset + self.pos)
+
+ ##
+ # Get current file pointer.
+ #
+ # @return Offset from start of region, in bytes.
+
+ def tell(self):
+ return self.pos
+
+ ##
+ # Read data.
+ #
+ # @def read(bytes=0)
+ # @param bytes Number of bytes to read. If omitted or zero,
+ # read until end of region.
+ # @return An 8-bit string.
+
+ def read(self, n = 0):
+ if n:
+ n = min(n, self.length - self.pos)
+ else:
+ n = self.length - self.pos
+ if not n: # EOF
+ return ""
+ self.pos = self.pos + n
+ return self.fh.read(n)
+
+ ##
+ # Read a line of text.
+ #
+ # @return An 8-bit string.
+
+ def readline(self):
+ s = ""
+ while 1:
+ c = self.read(1)
+ if not c:
+ break
+ s = s + c
+ if c == "\n":
+ break
+ return s
+
+ ##
+ # Read multiple lines of text.
+ #
+ # @return A list of 8-bit strings.
+
+ def readlines(self):
+ l = []
+ while 1:
+ s = self.readline()
+ if not s:
+ break
+ l.append(s)
+ return l
diff --git a/Imaging/PIL/CurImagePlugin.py b/Imaging/PIL/CurImagePlugin.py
new file mode 100644
index 0000000..b879da3
--- /dev/null
+++ b/Imaging/PIL/CurImagePlugin.py
@@ -0,0 +1,90 @@
+#
+# The Python Imaging Library.
+# $Id: CurImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# Windows Cursor support for PIL
+#
+# notes:
+# uses BmpImagePlugin.py to read the bitmap data.
+#
+# history:
+# 96-05-27 fl Created
+#
+# Copyright (c) Secret Labs AB 1997.
+# Copyright (c) Fredrik Lundh 1996.
+#
+# See the README file for information on usage and redistribution.
+#
+
+
+__version__ = "0.1"
+
+import string
+
+import Image, BmpImagePlugin
+
+
+#
+# --------------------------------------------------------------------
+
+def i16(c):
+ return ord(c[0]) + (ord(c[1])<<8)
+
+def i32(c):
+ return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
+
+
+def _accept(prefix):
+ return prefix[:4] == "\0\0\2\0"
+
+##
+# Image plugin for Windows Cursor files.
+
+class CurImageFile(BmpImagePlugin.BmpImageFile):
+
+ format = "CUR"
+ format_description = "Windows Cursor"
+
+ def _open(self):
+
+ offset = self.fp.tell()
+
+ # check magic
+ s = self.fp.read(6)
+ if not _accept(s):
+ raise SyntaxError, "not an CUR file"
+
+ # pick the largest cursor in the file
+ m = ""
+ 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
+ #print "width", ord(s[0])
+ #print "height", ord(s[1])
+ #print "colors", ord(s[2])
+ #print "reserved", ord(s[3])
+ #print "hotspot x", i16(s[4:])
+ #print "hotspot y", i16(s[6:])
+ #print "bytes", i32(s[8:])
+ #print "offset", i32(s[12:])
+
+ # load as bitmap
+ self._bitmap(i32(m[12:]) + offset)
+
+ # patch up the bitmap height
+ self.size = self.size[0], self.size[1]/2
+ d, e, o, a = self.tile[0]
+ self.tile[0] = d, (0,0)+self.size, o, a
+
+ return
+
+
+#
+# --------------------------------------------------------------------
+
+Image.register_open("CUR", CurImageFile, _accept)
+
+Image.register_extension("CUR", ".cur")
diff --git a/Imaging/PIL/DcxImagePlugin.py b/Imaging/PIL/DcxImagePlugin.py
new file mode 100644
index 0000000..3a0df01
--- /dev/null
+++ b/Imaging/PIL/DcxImagePlugin.py
@@ -0,0 +1,78 @@
+#
+# The Python Imaging Library.
+# $Id: DcxImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# DCX file handling
+#
+# DCX is a container file format defined by Intel, commonly used
+# for fax applications. Each DCX file consists of a directory
+# (a list of file offsets) followed by a set of (usually 1-bit)
+# PCX files.
+#
+# History:
+# 1995-09-09 fl Created
+# 1996-03-20 fl Properly derived from PcxImageFile.
+# 1998-07-15 fl Renamed offset attribute to avoid name clash
+# 2002-07-30 fl Fixed file handling
+#
+# Copyright (c) 1997-98 by Secret Labs AB.
+# Copyright (c) 1995-96 by Fredrik Lundh.
+#
+# See the README file for information on usage and redistribution.
+#
+
+__version__ = "0.2"
+
+import Image, ImageFile
+
+from PcxImagePlugin import PcxImageFile
+
+MAGIC = 0x3ADE68B1 # QUIZ: what's this value, then?
+
+def i32(c):
+ return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
+
+def _accept(prefix):
+ return i32(prefix) == MAGIC
+
+##
+# Image plugin for the Intel DCX format.
+
+class DcxImageFile(PcxImageFile):
+
+ format = "DCX"
+ format_description = "Intel DCX"
+
+ def _open(self):
+
+ # Header
+ s = self.fp.read(4)
+ if i32(s) != MAGIC:
+ raise SyntaxError, "not a DCX file"
+
+ # Component directory
+ self._offset = []
+ for i in range(1024):
+ offset = i32(self.fp.read(4))
+ if not offset:
+ break
+ self._offset.append(offset)
+
+ self.__fp = self.fp
+ self.seek(0)
+
+ def seek(self, frame):
+ if frame >= len(self._offset):
+ raise EOFError("attempt to seek outside DCX directory")
+ self.frame = frame
+ self.fp = self.__fp
+ self.fp.seek(self._offset[frame])
+ PcxImageFile._open(self)
+
+ def tell(self):
+ return self.frame
+
+
+Image.register_open("DCX", DcxImageFile, _accept)
+
+Image.register_extension("DCX", ".dcx")
diff --git a/Imaging/PIL/EpsImagePlugin.py b/Imaging/PIL/EpsImagePlugin.py
new file mode 100644
index 0000000..e0a608e
--- /dev/null
+++ b/Imaging/PIL/EpsImagePlugin.py
@@ -0,0 +1,349 @@
+#
+# The Python Imaging Library.
+# $Id: EpsImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# EPS file handling
+#
+# History:
+# 1995-09-01 fl Created (0.1)
+# 1996-05-18 fl Don't choke on "atend" fields, Ghostscript interface (0.2)
+# 1996-08-22 fl Don't choke on floating point BoundingBox values
+# 1996-08-23 fl Handle files from Macintosh (0.3)
+# 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.4)
+# 2003-09-07 fl Check gs.close status (from Federico Di Gregorio) (0.5)
+#
+# Copyright (c) 1997-2003 by Secret Labs AB.
+# Copyright (c) 1995-2003 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+__version__ = "0.5"
+
+import re, string
+import Image, ImageFile
+
+#
+# --------------------------------------------------------------------
+
+def i32(c):
+ return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
+
+def o32(i):
+ return chr(i&255) + chr(i>>8&255) + chr(i>>16&255) + chr(i>>24&255)
+
+split = re.compile(r"^%%([^:]*):[ \t]*(.*)[ \t]*$")
+field = re.compile(r"^%[%!\w]([^:]*)[ \t]*$")
+
+def Ghostscript(tile, size, fp):
+ """Render an image using Ghostscript (Unix only)"""
+
+ # Unpack decoder tile
+ decoder, tile, offset, data = tile[0]
+ length, bbox = data
+
+ import tempfile, os
+
+ file = tempfile.mktemp()
+
+ # Build ghostscript command
+ command = ["gs",
+ "-q", # quite mode
+ "-g%dx%d" % size, # set output geometry (pixels)
+ "-dNOPAUSE -dSAFER", # don't pause between pages, safe mode
+ "-sDEVICE=ppmraw", # ppm driver
+ "-sOutputFile=%s" % file,# output file
+ "- >/dev/null 2>/dev/null"]
+
+ command = string.join(command)
+
+ # push data through ghostscript
+ try:
+ gs = os.popen(command, "w")
+ # adjust for image origin
+ if bbox[0] != 0 or bbox[1] != 0:
+ gs.write("%d %d translate\n" % (-bbox[0], -bbox[1]))
+ fp.seek(offset)
+ while length > 0:
+ s = fp.read(8192)
+ if not s:
+ break
+ length = length - len(s)
+ gs.write(s)
+ status = gs.close()
+ if status:
+ raise IOError("gs failed (status %d)" % status)
+ im = Image.core.open_ppm(file)
+ finally:
+ try: os.unlink(file)
+ except: pass
+
+ return im
+
+
+class PSFile:
+ """Wrapper that treats either CR or LF as end of line."""
+ def __init__(self, fp):
+ self.fp = fp
+ self.char = None
+ def __getattr__(self, id):
+ v = getattr(self.fp, id)
+ setattr(self, id, v)
+ return v
+ def seek(self, offset, whence=0):
+ self.char = None
+ self.fp.seek(offset, whence)
+ def tell(self):
+ pos = self.fp.tell()
+ if self.char:
+ pos = pos - 1
+ return pos
+ def readline(self):
+ s = ""
+ if self.char:
+ c = self.char
+ self.char = None
+ else:
+ c = self.fp.read(1)
+ while c not in "\r\n":
+ s = s + c
+ c = self.fp.read(1)
+ if c == "\r":
+ self.char = self.fp.read(1)
+ if self.char == "\n":
+ self.char = None
+ return s + "\n"
+
+
+def _accept(prefix):
+ return prefix[:4] == "%!PS" or i32(prefix) == 0xC6D3D0C5L
+
+##
+# Image plugin for Encapsulated Postscript. This plugin supports only
+# a few variants of this format.
+
+class EpsImageFile(ImageFile.ImageFile):
+ """EPS File Parser for the Python Imaging Library"""
+
+ format = "EPS"
+ format_description = "Encapsulated Postscript"
+
+ def _open(self):
+
+ # FIXME: should check the first 512 bytes to see if this
+ # really is necessary (platform-dependent, though...)
+
+ fp = PSFile(self.fp)
+
+ # HEAD
+ s = fp.read(512)
+ if s[:4] == "%!PS":
+ offset = 0
+ fp.seek(0, 2)
+ length = fp.tell()
+ elif i32(s) == 0xC6D3D0C5L:
+ offset = i32(s[4:])
+ length = i32(s[8:])
+ fp.seek(offset)
+ else:
+ raise SyntaxError, "not an EPS file"
+
+ fp.seek(offset)
+
+ box = None
+
+ self.mode = "RGB"
+ self.size = 1, 1 # FIXME: huh?
+
+ #
+ # Load EPS header
+
+ s = fp.readline()
+
+ while s:
+
+ if len(s) > 255:
+ raise SyntaxError, "not an EPS file"
+
+ if s[-2:] == '\r\n':
+ s = s[:-2]
+ elif s[-1:] == '\n':
+ s = s[:-1]
+
+ try:
+ m = split.match(s)
+ except re.error, v:
+ raise SyntaxError, "not an EPS file"
+
+ if m:
+ k, v = m.group(1, 2)
+ self.info[k] = v
+ if k == "BoundingBox":
+ try:
+ # Note: The DSC spec says that BoundingBox
+ # fields should be integers, but some drivers
+ # put floating point values there anyway.
+ box = map(int, map(float, string.split(v)))
+ self.size = box[2] - box[0], box[3] - box[1]
+ self.tile = [("eps", (0,0) + self.size, offset,
+ (length, box))]
+ except:
+ pass
+
+ else:
+
+ m = field.match(s)
+
+ if m:
+ k = m.group(1)
+ if k == "EndComments":
+ break
+ if k[:8] == "PS-Adobe":
+ self.info[k[:8]] = k[9:]
+ else:
+ self.info[k] = ""
+ else:
+ raise IOError, "bad EPS header"
+
+ s = fp.readline()
+
+ if s[:1] != "%":
+ break
+
+
+ #
+ # Scan for an "ImageData" descriptor
+
+ while s[0] == "%":
+
+ if len(s) > 255:
+ raise SyntaxError, "not an EPS file"
+
+ if s[-2:] == '\r\n':
+ s = s[:-2]
+ elif s[-1:] == '\n':
+ s = s[:-1]
+
+ if s[:11] == "%ImageData:":
+
+ [x, y, bi, mo, z3, z4, en, id] =\
+ string.split(s[11:], maxsplit=7)
+
+ x = int(x); y = int(y)
+
+ bi = int(bi)
+ mo = int(mo)
+
+ en = int(en)
+
+ if en == 1:
+ decoder = "eps_binary"
+ elif en == 2:
+ decoder = "eps_hex"
+ else:
+ break
+ if bi != 8:
+ break
+ if mo == 1:
+ self.mode = "L"
+ elif mo == 2:
+ self.mode = "LAB"
+ elif mo == 3:
+ self.mode = "RGB"
+ else:
+ break
+
+ if id[:1] == id[-1:] == '"':
+ id = id[1:-1]
+
+ # Scan forward to the actual image data
+ while 1:
+ s = fp.readline()
+ if not s:
+ break
+ if s[:len(id)] == id:
+ self.size = x, y
+ self.tile2 = [(decoder,
+ (0, 0, x, y),
+ fp.tell(),
+ 0)]
+ return
+
+ s = fp.readline()
+ if not s:
+ break
+
+ if not box:
+ raise IOError, "cannot determine EPS bounding box"
+
+ def load(self):
+ # Load EPS via Ghostscript
+ if not self.tile:
+ return
+ self.im = Ghostscript(self.tile, self.size, self.fp)
+ self.mode = self.im.mode
+ self.size = self.im.size
+ self.tile = []
+
+#
+# --------------------------------------------------------------------
+
+def _save(im, fp, filename, eps=1):
+ """EPS Writer for the Python Imaging Library."""
+
+ #
+ # make sure image data is available
+ im.load()
+
+ #
+ # determine postscript image mode
+ if im.mode == "L":
+ operator = (8, 1, "image")
+ elif im.mode == "RGB":
+ operator = (8, 3, "false 3 colorimage")
+ elif im.mode == "CMYK":
+ operator = (8, 4, "false 4 colorimage")
+ else:
+ raise ValueError, "image mode is not supported"
+
+ if eps:
+ #
+ # write EPS header
+ fp.write("%!PS-Adobe-3.0 EPSF-3.0\n")
+ fp.write("%%Creator: PIL 0.1 EpsEncode\n")
+ #fp.write("%%CreationDate: %s"...)
+ fp.write("%%%%BoundingBox: 0 0 %d %d\n" % im.size)
+ fp.write("%%Pages: 1\n")
+ fp.write("%%EndComments\n")
+ fp.write("%%Page: 1 1\n")
+ fp.write("%%ImageData: %d %d " % im.size)
+ fp.write("%d %d 0 1 1 \"%s\"\n" % operator)
+
+ #
+ # image header
+ fp.write("gsave\n")
+ fp.write("10 dict begin\n")
+ fp.write("/buf %d string def\n" % (im.size[0] * operator[1]))
+ fp.write("%d %d scale\n" % im.size)
+ fp.write("%d %d 8\n" % im.size) # <= bits
+ fp.write("[%d 0 0 -%d 0 %d]\n" % (im.size[0], im.size[1], im.size[1]))
+ fp.write("{ currentfile buf readhexstring pop } bind\n")
+ fp.write("%s\n" % operator[2])
+
+ ImageFile._save(im, fp, [("eps", (0,0)+im.size, 0, None)])
+
+ fp.write("\n%%%%EndBinary\n")
+ fp.write("grestore end\n")
+ fp.flush()
+
+#
+# --------------------------------------------------------------------
+
+Image.register_open(EpsImageFile.format, EpsImageFile, _accept)
+
+Image.register_save(EpsImageFile.format, _save)
+
+Image.register_extension(EpsImageFile.format, ".ps")
+Image.register_extension(EpsImageFile.format, ".eps")
+
+Image.register_mime(EpsImageFile.format, "application/postscript")
diff --git a/Imaging/PIL/ExifTags.py b/Imaging/PIL/ExifTags.py
new file mode 100644
index 0000000..01a6b74
--- /dev/null
+++ b/Imaging/PIL/ExifTags.py
@@ -0,0 +1,157 @@
+#
+# The Python Imaging Library.
+# $Id: ExifTags.py 2631 2006-02-12 23:41:52Z fredrik $
+#
+# EXIF tags
+#
+# Copyright (c) 2003 by Secret Labs AB
+#
+# See the README file for information on usage and redistribution.
+#
+
+##
+# This module provides constants and clear-text names for various
+# well-known EXIF tags.
+##
+
+##
+# Maps EXIF tags to tag names.
+
+TAGS = {
+
+ # possibly incomplete
+ 0x0100: "ImageWidth",
+ 0x0101: "ImageLength",
+ 0x0102: "BitsPerSample",
+ 0x0103: "Compression",
+ 0x0106: "PhotometricInterpretation",
+ 0x010e: "ImageDescription",
+ 0x010f: "Make",
+ 0x0110: "Model",
+ 0x0111: "StripOffsets",
+ 0x0112: "Orientation",
+ 0x0115: "SamplesPerPixel",
+ 0x0116: "RowsPerStrip",
+ 0x0117: "StripByteConunts",
+ 0x011a: "XResolution",
+ 0x011a: "XResolution",
+ 0x011b: "YResolution",
+ 0x011b: "YResolution",
+ 0x011c: "PlanarConfiguration",
+ 0x0128: "ResolutionUnit",
+ 0x0128: "ResolutionUnit",
+ 0x012d: "TransferFunction",
+ 0x0131: "Software",
+ 0x0132: "DateTime",
+ 0x013b: "Artist",
+ 0x013e: "WhitePoint",
+ 0x013f: "PrimaryChromaticities",
+ 0x0201: "JpegIFOffset",
+ 0x0202: "JpegIFByteCount",
+ 0x0211: "YCbCrCoefficients",
+ 0x0211: "YCbCrCoefficients",
+ 0x0212: "YCbCrSubSampling",
+ 0x0213: "YCbCrPositioning",
+ 0x0213: "YCbCrPositioning",
+ 0x0214: "ReferenceBlackWhite",
+ 0x0214: "ReferenceBlackWhite",
+ 0x1000: "RelatedImageFileFormat",
+ 0x1001: "RelatedImageLength",
+ 0x1001: "RelatedImageWidth",
+ 0x828d: "CFARepeatPatternDim",
+ 0x828e: "CFAPattern",
+ 0x828f: "BatteryLevel",
+ 0x8298: "Copyright",
+ 0x829a: "ExposureTime",
+ 0x829d: "FNumber",
+ 0x8769: "ExifOffset",
+ 0x8773: "InterColorProfile",
+ 0x8822: "ExposureProgram",
+ 0x8824: "SpectralSensitivity",
+ 0x8825: "GPSInfo",
+ 0x8827: "ISOSpeedRatings",
+ 0x8828: "OECF",
+ 0x8829: "Interlace",
+ 0x882a: "TimeZoneOffset",
+ 0x882b: "SelfTimerMode",
+ 0x9000: "ExifVersion",
+ 0x9003: "DateTimeOriginal",
+ 0x9004: "DateTimeDigitized",
+ 0x9101: "ComponentsConfiguration",
+ 0x9102: "CompressedBitsPerPixel",
+ 0x9201: "ShutterSpeedValue",
+ 0x9202: "ApertureValue",
+ 0x9203: "BrightnessValue",
+ 0x9204: "ExposureBiasValue",
+ 0x9205: "MaxApertureValue",
+ 0x9206: "SubjectDistance",
+ 0x9207: "MeteringMode",
+ 0x9208: "LightSource",
+ 0x9209: "Flash",
+ 0x920a: "FocalLength",
+ 0x920b: "FlashEnergy",
+ 0x920c: "SpatialFrequencyResponse",
+ 0x920d: "Noise",
+ 0x9211: "ImageNumber",
+ 0x9212: "SecurityClassification",
+ 0x9213: "ImageHistory",
+ 0x9214: "SubjectLocation",
+ 0x9215: "ExposureIndex",
+ 0x9216: "TIFF/EPStandardID",
+ 0x927c: "MakerNote",
+ 0x9286: "UserComment",
+ 0x9290: "SubsecTime",
+ 0x9291: "SubsecTimeOriginal",
+ 0x9292: "SubsecTimeDigitized",
+ 0xa000: "FlashPixVersion",
+ 0xa001: "ColorSpace",
+ 0xa002: "ExifImageWidth",
+ 0xa003: "ExifImageHeight",
+ 0xa004: "RelatedSoundFile",
+ 0xa005: "ExifInteroperabilityOffset",
+ 0xa20b: "FlashEnergy",
+ 0xa20c: "SpatialFrequencyResponse",
+ 0xa20e: "FocalPlaneXResolution",
+ 0xa20f: "FocalPlaneYResolution",
+ 0xa210: "FocalPlaneResolutionUnit",
+ 0xa214: "SubjectLocation",
+ 0xa215: "ExposureIndex",
+ 0xa217: "SensingMethod",
+ 0xa300: "FileSource",
+ 0xa301: "SceneType",
+ 0xa302: "CFAPattern",
+
+}
+
+##
+# Maps EXIF GSP tags to tag names.
+
+GPSTAGS = {
+ 0: "GPSVersionID",
+ 1: "GPSLatitudeRef",
+ 2: "GPSLatitude",
+ 3: "GPSLongitudeRef",
+ 4: "GPSLongitude",
+ 5: "GPSAltitudeRef",
+ 6: "GPSAltitude",
+ 7: "GPSTimeStamp",
+ 8: "GPSSatellites",
+ 9: "GPSStatus",
+ 10: "GPSMeasureMode",
+ 11: "GPSDOP",
+ 12: "GPSSpeedRef",
+ 13: "GPSSpeed",
+ 14: "GPSTrackRef",
+ 15: "GPSTrack",
+ 16: "GPSImgDirectionRef",
+ 17: "GPSImgDirection",
+ 18: "GPSMapDatum",
+ 19: "GPSDestLatitudeRef",
+ 20: "GPSDestLatitude",
+ 21: "GPSDestLongitudeRef",
+ 22: "GPSDestLongitude",
+ 23: "GPSDestBearingRef",
+ 24: "GPSDestBearing",
+ 25: "GPSDestDistanceRef",
+ 26: "GPSDestDistance"
+}
diff --git a/Imaging/PIL/FitsStubImagePlugin.py b/Imaging/PIL/FitsStubImagePlugin.py
new file mode 100644
index 0000000..05f5d46
--- /dev/null
+++ b/Imaging/PIL/FitsStubImagePlugin.py
@@ -0,0 +1,73 @@
+#
+# The Python Imaging Library
+# $Id: FitsStubImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# FITS stub adapter
+#
+# Copyright (c) 1998-2003 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image, ImageFile
+
+_handler = None
+
+##
+# Install application-specific FITS image handler.
+#
+# @param handler Handler object.
+
+def register_handler(handler):
+ global _handler
+ _handler = handler
+
+# --------------------------------------------------------------------
+# Image adapter
+
+def _accept(prefix):
+ return prefix[:6] == "SIMPLE"
+
+class FITSStubImageFile(ImageFile.StubImageFile):
+
+ format = "FITS"
+ format_description = "FITS"
+
+ def _open(self):
+
+ offset = self.fp.tell()
+
+ if not _accept(self.fp.read(6)):
+ raise SyntaxError("Not a FITS file")
+
+ # FIXME: add more sanity checks here; mandatory header items
+ # include SIMPLE, BITPIX, NAXIS, etc.
+
+ self.fp.seek(offset)
+
+ # make something up
+ self.mode = "F"
+ self.size = 1, 1
+
+ loader = self._load()
+ if loader:
+ loader.open(self)
+
+ def _load(self):
+ return _handler
+
+
+def _save(im, fp, filename):
+ if _handler is None or not hasattr("_handler", "save"):
+ raise IOError("FITS save handler not installed")
+ _handler.save(im, fp, filename)
+
+
+# --------------------------------------------------------------------
+# Registry
+
+Image.register_open(FITSStubImageFile.format, FITSStubImageFile, _accept)
+Image.register_save(FITSStubImageFile.format, _save)
+
+Image.register_extension(FITSStubImageFile.format, ".fit")
+Image.register_extension(FITSStubImageFile.format, ".fits")
diff --git a/Imaging/PIL/FliImagePlugin.py b/Imaging/PIL/FliImagePlugin.py
new file mode 100644
index 0000000..5b1bf8e
--- /dev/null
+++ b/Imaging/PIL/FliImagePlugin.py
@@ -0,0 +1,142 @@
+#
+# The Python Imaging Library.
+# $Id: FliImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# FLI/FLC file handling.
+#
+# History:
+# 95-09-01 fl Created
+# 97-01-03 fl Fixed parser, setup decoder tile
+# 98-07-15 fl Renamed offset attribute to avoid name clash
+#
+# Copyright (c) Secret Labs AB 1997-98.
+# Copyright (c) Fredrik Lundh 1995-97.
+#
+# See the README file for information on usage and redistribution.
+#
+
+
+__version__ = "0.2"
+
+import Image, ImageFile, ImagePalette
+import string
+
+
+def i16(c):
+ return ord(c[0]) + (ord(c[1])<<8)
+
+def i32(c):
+ return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
+
+#
+# decoder
+
+def _accept(prefix):
+ return i16(prefix[4:6]) in [0xAF11, 0xAF12]
+
+##
+# Image plugin for the FLI/FLC animation format. Use the <b>seek</b>
+# method to load individual frames.
+
+class FliImageFile(ImageFile.ImageFile):
+
+ format = "FLI"
+ format_description = "Autodesk FLI/FLC Animation"
+
+ def _open(self):
+
+ # HEAD
+ s = self.fp.read(128)
+ magic = i16(s[4:6])
+ if magic not in [0xAF11, 0xAF12]:
+ raise SyntaxError, "not an FLI/FLC file"
+
+ # image characteristics
+ self.mode = "P"
+ self.size = i16(s[8:10]), i16(s[10:12])
+
+ # animation speed
+ duration = i32(s[16:20])
+ if magic == 0xAF11:
+ duration = (duration * 1000) / 70
+ self.info["duration"] = duration
+
+ # look for palette
+ palette = map(lambda a: (a,a,a), range(256))
+
+ s = self.fp.read(16)
+
+ self.__offset = 128
+
+ if i16(s[4:6]) == 0xF100:
+ # prefix chunk; ignore it
+ self.__offset = self.__offset + i32(s)
+ s = self.fp.read(16)
+
+ if i16(s[4:6]) == 0xF1FA:
+ # look for palette chunk
+ s = self.fp.read(6)
+ if i16(s[4:6]) == 11:
+ self._palette(palette, 2)
+ elif i16(s[4:6]) == 4:
+ self._palette(palette, 0)
+
+ palette = map(lambda (r,g,b): chr(r)+chr(g)+chr(b), palette)
+ self.palette = ImagePalette.raw("RGB", string.join(palette, ""))
+
+ # set things up to decode first frame
+ self.frame = -1
+ self.__fp = self.fp
+
+ self.seek(0)
+
+ def _palette(self, palette, shift):
+ # load palette
+
+ i = 0
+ for e in range(i16(self.fp.read(2))):
+ s = self.fp.read(2)
+ i = i + ord(s[0])
+ n = ord(s[1])
+ if n == 0:
+ n = 256
+ s = self.fp.read(n * 3)
+ for n in range(0, len(s), 3):
+ r = ord(s[n]) << shift
+ g = ord(s[n+1]) << shift
+ b = ord(s[n+2]) << shift
+ palette[i] = (r, g, b)
+ i = i + 1
+
+ def seek(self, frame):
+
+ if frame != self.frame + 1:
+ raise ValueError, "cannot seek to frame %d" % frame
+ self.frame = frame
+
+ # move to next frame
+ self.fp = self.__fp
+ self.fp.seek(self.__offset)
+
+ s = self.fp.read(4)
+ if not s:
+ raise EOFError
+
+ framesize = i32(s)
+
+ self.decodermaxblock = framesize
+ self.tile = [("fli", (0,0)+self.size, self.__offset, None)]
+
+ self.__offset = self.__offset + framesize
+
+ def tell(self):
+
+ return self.frame
+
+#
+# registry
+
+Image.register_open("FLI", FliImageFile, _accept)
+
+Image.register_extension("FLI", ".fli")
+Image.register_extension("FLI", ".flc")
diff --git a/Imaging/PIL/FontFile.py b/Imaging/PIL/FontFile.py
new file mode 100644
index 0000000..bf4b905
--- /dev/null
+++ b/Imaging/PIL/FontFile.py
@@ -0,0 +1,146 @@
+#
+# The Python Imaging Library
+# $Id: FontFile.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# base class for raster font file parsers
+#
+# history:
+# 1997-06-05 fl created
+# 1997-08-19 fl restrict image width
+#
+# Copyright (c) 1997-1998 by Secret Labs AB
+# Copyright (c) 1997-1998 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+import os
+import Image
+
+import marshal
+
+try:
+ import zlib
+except ImportError:
+ zlib = None
+
+WIDTH = 800
+
+def puti16(fp, values):
+ # write network order (big-endian) 16-bit sequence
+ for v in values:
+ if v < 0:
+ v = v + 65536
+ fp.write(chr(v>>8&255) + chr(v&255))
+
+##
+# Base class for raster font file handlers.
+
+class FontFile:
+
+ bitmap = None
+
+ def __init__(self):
+
+ self.info = {}
+ self.glyph = [None] * 256
+
+ def __getitem__(self, ix):
+ return self.glyph[ix]
+
+ def compile(self):
+ "Create metrics and bitmap"
+
+ if self.bitmap:
+ return
+
+ # create bitmap large enough to hold all data
+ h = w = maxwidth = 0
+ lines = 1
+ for glyph in self:
+ if glyph:
+ d, dst, src, im = glyph
+ h = max(h, src[3] - src[1])
+ w = w + (src[2] - src[0])
+ if w > WIDTH:
+ lines = lines + 1
+ w = (src[2] - src[0])
+ maxwidth = max(maxwidth, w)
+
+ xsize = maxwidth
+ ysize = lines * h
+
+ if xsize == 0 and ysize == 0:
+ return ""
+
+ self.ysize = h
+
+ # paste glyphs into bitmap
+ self.bitmap = Image.new("1", (xsize, ysize))
+ self.metrics = [None] * 256
+ x = y = 0
+ for i in range(256):
+ glyph = self[i]
+ if glyph:
+ d, dst, src, im = glyph
+ xx, yy = src[2] - src[0], src[3] - src[1]
+ x0, y0 = x, y
+ x = x + xx
+ if x > WIDTH:
+ x, y = 0, y + h
+ x0, y0 = x, y
+ x = xx
+ s = src[0] + x0, src[1] + y0, src[2] + x0, src[3] + y0
+ self.bitmap.paste(im.crop(src), s)
+ # print chr(i), dst, s
+ self.metrics[i] = d, dst, s
+
+
+ def save1(self, filename):
+ "Save font in version 1 format"
+
+ self.compile()
+
+ # font data
+ self.bitmap.save(os.path.splitext(filename)[0] + ".pbm", "PNG")
+
+ # font metrics
+ fp = open(os.path.splitext(filename)[0] + ".pil", "wb")
+ fp.write("PILfont\n")
+ fp.write(";;;;;;%d;\n" % self.ysize) # HACK!!!
+ fp.write("DATA\n")
+ for id in range(256):
+ m = self.metrics[id]
+ if not m:
+ puti16(fp, [0] * 10)
+ else:
+ puti16(fp, m[0] + m[1] + m[2])
+ fp.close()
+
+
+ def save2(self, filename):
+ "Save font in version 2 format"
+
+ # THIS IS WORK IN PROGRESS
+
+ self.compile()
+
+ data = marshal.dumps((self.metrics, self.info))
+
+ if zlib:
+ data = "z" + zlib.compress(data, 9)
+ else:
+ data = "u" + data
+
+ fp = open(os.path.splitext(filename)[0] + ".pil", "wb")
+
+ fp.write("PILfont2\n" + self.name + "\n" + "DATA\n")
+
+ fp.write(data)
+
+ self.bitmap.save(fp, "PNG")
+
+ fp.close()
+
+
+ save = save1 # for now
diff --git a/Imaging/PIL/FpxImagePlugin.py b/Imaging/PIL/FpxImagePlugin.py
new file mode 100644
index 0000000..d4a1aef
--- /dev/null
+++ b/Imaging/PIL/FpxImagePlugin.py
@@ -0,0 +1,226 @@
+#
+# THIS IS WORK IN PROGRESS
+#
+# The Python Imaging Library.
+# $Id: FpxImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# FlashPix support for PIL
+#
+# History:
+# 97-01-25 fl Created (reads uncompressed RGB images only)
+#
+# Copyright (c) Secret Labs AB 1997.
+# Copyright (c) Fredrik Lundh 1997.
+#
+# See the README file for information on usage and redistribution.
+#
+
+
+__version__ = "0.1"
+
+
+import string
+
+import Image, ImageFile
+from OleFileIO import *
+
+
+# we map from colour field tuples to (mode, rawmode) descriptors
+MODES = {
+ # opacity
+ (0x00007ffe): ("A", "L"),
+ # monochrome
+ (0x00010000,): ("L", "L"),
+ (0x00018000, 0x00017ffe): ("RGBA", "LA"),
+ # photo YCC
+ (0x00020000, 0x00020001, 0x00020002): ("RGB", "YCC;P"),
+ (0x00028000, 0x00028001, 0x00028002, 0x00027ffe): ("RGBA", "YCCA;P"),
+ # standard RGB (NIFRGB)
+ (0x00030000, 0x00030001, 0x00030002): ("RGB","RGB"),
+ (0x00038000, 0x00038001, 0x00038002, 0x00037ffe): ("RGBA","RGBA"),
+}
+
+#
+# --------------------------------------------------------------------
+
+def _accept(prefix):
+ return prefix[:8] == MAGIC
+
+##
+# Image plugin for the FlashPix images.
+
+class FpxImageFile(ImageFile.ImageFile):
+
+ format = "FPX"
+ format_description = "FlashPix"
+
+ def _open(self):
+ #
+ # read the OLE directory and see if this is a likely
+ # to be a FlashPix file
+
+ try:
+ self.ole = OleFileIO(self.fp)
+ except IOError:
+ raise SyntaxError, "not an FPX file; invalid OLE file"
+
+ if self.ole.root.clsid != "56616700-C154-11CE-8553-00AA00A1F95B":
+ raise SyntaxError, "not an FPX file; bad root CLSID"
+
+ self._open_index(1)
+
+ def _open_index(self, index = 1):
+ #
+ # get the Image Contents Property Set
+
+ prop = self.ole.getproperties([
+ "Data Object Store %06d" % index,
+ "\005Image Contents"
+ ])
+
+ # size (highest resolution)
+
+ self.size = prop[0x1000002], prop[0x1000003]
+
+ size = max(self.size)
+ i = 1
+ while size > 64:
+ size = size / 2
+ i = i + 1
+ self.maxid = i - 1
+
+ # mode. instead of using a single field for this, flashpix
+ # requires you to specify the mode for each channel in each
+ # resolution subimage, and leaves it to the decoder to make
+ # sure that they all match. for now, we'll cheat and assume
+ # that this is always the case.
+
+ id = self.maxid << 16
+
+ s = prop[0x2000002|id]
+
+ colors = []
+ for i in range(i32(s, 4)):
+ # note: for now, we ignore the "uncalibrated" flag
+ colors.append(i32(s, 8+i*4) & 0x7fffffff)
+
+ self.mode, self.rawmode = MODES[tuple(colors)]
+
+ # load JPEG tables, if any
+ self.jpeg = {}
+ for i in range(256):
+ id = 0x3000001|(i << 16)
+ if prop.has_key(id):
+ self.jpeg[i] = prop[id]
+
+ # print len(self.jpeg), "tables loaded"
+
+ self._open_subimage(1, self.maxid)
+
+ def _open_subimage(self, index = 1, subimage = 0):
+ #
+ # setup tile descriptors for a given subimage
+
+ stream = [
+ "Data Object Store %06d" % index,
+ "Resolution %04d" % subimage,
+ "Subimage 0000 Header"
+ ]
+
+ fp = self.ole.openstream(stream)
+
+ # skip prefix
+ p = fp.read(28)
+
+ # header stream
+ s = fp.read(36)
+
+ size = i32(s, 4), i32(s, 8)
+ tilecount = i32(s, 12)
+ tilesize = i32(s, 16), i32(s, 20)
+ channels = i32(s, 24)
+ offset = i32(s, 28)
+ length = i32(s, 32)
+
+ # print size, self.mode, self.rawmode
+
+ if size != self.size:
+ raise IOError, "subimage mismatch"
+
+ # get tile descriptors
+ fp.seek(28 + offset)
+ s = fp.read(i32(s, 12) * length)
+
+ x = y = 0
+ xsize, ysize = size
+ xtile, ytile = tilesize
+ self.tile = []
+
+ for i in range(0, len(s), length):
+
+ compression = i32(s, i+8)
+
+ if compression == 0:
+ self.tile.append(("raw", (x,y,x+xtile,y+ytile),
+ i32(s, i) + 28, (self.rawmode)))
+
+ elif compression == 1:
+
+ # FIXME: the fill decoder is not implemented
+ self.tile.append(("fill", (x,y,x+xtile,y+ytile),
+ i32(s, i) + 28, (self.rawmode, s[12:16])))
+
+ elif compression == 2:
+
+ internal_color_conversion = ord(s[14])
+ jpeg_tables = ord(s[15])
+ rawmode = self.rawmode
+
+ if internal_color_conversion:
+ # The image is stored as usual (usually YCbCr).
+ if rawmode == "RGBA":
+ # For "RGBA", data is stored as YCbCrA based on
+ # negative RGB. The following trick works around
+ # this problem :
+ jpegmode, rawmode = "YCbCrK", "CMYK"
+ else:
+ jpegmode = None # let the decoder decide
+
+ else:
+ # The image is stored as defined by rawmode
+ jpegmode = rawmode
+
+ self.tile.append(("jpeg", (x,y,x+xtile,y+ytile),
+ i32(s, i) + 28, (rawmode, jpegmode)))
+
+ # FIXME: jpeg tables are tile dependent; the prefix
+ # data must be placed in the tile descriptor itself!
+
+ if jpeg_tables:
+ self.tile_prefix = self.jpeg[jpeg_tables]
+
+ else:
+ raise IOError, "unknown/invalid compression"
+
+ x = x + xtile
+ if x >= xsize:
+ x, y = 0, y + ytile
+ if y >= ysize:
+ break # isn't really required
+
+ self.stream = stream
+ self.fp = None
+
+ def load(self):
+
+ if not self.fp:
+ self.fp = self.ole.openstream(self.stream[:2] + ["Subimage 0000 Data"])
+
+ ImageFile.ImageFile.load(self)
+
+#
+# --------------------------------------------------------------------
+
+Image.register_open("FPX", FpxImageFile, _accept)
+
+Image.register_extension("FPX", ".fpx")
diff --git a/Imaging/PIL/GbrImagePlugin.py b/Imaging/PIL/GbrImagePlugin.py
new file mode 100644
index 0000000..273e1f8
--- /dev/null
+++ b/Imaging/PIL/GbrImagePlugin.py
@@ -0,0 +1,70 @@
+#
+# The Python Imaging Library
+# $Id: GbrImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# load a GIMP brush file
+#
+# History:
+# 96-03-14 fl Created
+#
+# Copyright (c) Secret Labs AB 1997.
+# Copyright (c) Fredrik Lundh 1996.
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image, ImageFile
+
+def i32(c):
+ return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24L)
+
+def _accept(prefix):
+ return i32(prefix) >= 20 and i32(prefix[4:8]) == 1
+
+##
+# Image plugin for the GIMP brush format.
+
+class GbrImageFile(ImageFile.ImageFile):
+
+ format = "GBR"
+ format_description = "GIMP brush file"
+
+ def _open(self):
+
+ header_size = i32(self.fp.read(4))
+ version = i32(self.fp.read(4))
+ if header_size < 20 or version != 1:
+ raise SyntaxError, "not a GIMP brush"
+
+ width = i32(self.fp.read(4))
+ height = i32(self.fp.read(4))
+ bytes = i32(self.fp.read(4))
+ if width <= 0 or height <= 0 or bytes != 1:
+ raise SyntaxError, "not a GIMP brush"
+
+ comment = self.fp.read(header_size - 20)[:-1]
+
+ self.mode = "L"
+ self.size = width, height
+
+ self.info["comment"] = comment
+
+ # Since the brush is so small, we read the data immediately
+ self.data = self.fp.read(width * height)
+
+ def load(self):
+
+ if not self.data:
+ return
+
+ # create an image out of the brush data block
+ self.im = Image.core.new(self.mode, self.size)
+ self.im.fromstring(self.data)
+ self.data = ""
+
+#
+# registry
+
+Image.register_open("GBR", GbrImageFile, _accept)
+
+Image.register_extension("GBR", ".gbr")
diff --git a/Imaging/PIL/GdImageFile.py b/Imaging/PIL/GdImageFile.py
new file mode 100644
index 0000000..e6ddfa7
--- /dev/null
+++ b/Imaging/PIL/GdImageFile.py
@@ -0,0 +1,86 @@
+#
+# The Python Imaging Library.
+# $Id: GdImageFile.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# GD file handling
+#
+# History:
+# 1996-04-12 fl Created
+#
+# Copyright (c) 1997 by Secret Labs AB.
+# Copyright (c) 1996 by Fredrik Lundh.
+#
+# See the README file for information on usage and redistribution.
+#
+
+
+# NOTE: This format cannot be automatically recognized, so the
+# class is not registered for use with Image.open(). To open a
+# gd file, use the GdImageFile.open() function instead.
+
+# THE GD FORMAT IS NOT DESIGNED FOR DATA INTERCHANGE. This
+# implementation is provided for convenience and demonstrational
+# purposes only.
+
+
+__version__ = "0.1"
+
+import string
+import Image, ImageFile, ImagePalette
+
+def i16(c):
+ return ord(c[1]) + (ord(c[0])<<8)
+
+##
+# Image plugin for the GD uncompressed format. Note that this format
+# is not supported by the standard <b>Image.open</b> function. To use
+# this plugin, you have to import the <b>GdImageFile</b> module and
+# use the <b>GdImageFile.open</b> function.
+
+class GdImageFile(ImageFile.ImageFile):
+
+ format = "GD"
+ format_description = "GD uncompressed images"
+
+ def _open(self):
+
+ # Header
+ s = self.fp.read(775)
+
+ self.mode = "L" # FIXME: "P"
+ self.size = i16(s[0:2]), i16(s[2:4])
+
+ # transparency index
+ tindex = i16(s[5:7])
+ if tindex < 256:
+ self.info["transparent"] = tindex
+
+ self.palette = ImagePalette.raw("RGB", s[7:])
+
+ self.tile = [("raw", (0,0)+self.size, 775, ("L", 0, -1))]
+
+##
+# Load texture from a GD image file.
+#
+# @param filename GD file name, or an opened file handle.
+# @param mode Optional mode. In this version, if the mode argument
+# is given, it must be "r".
+# @return An image instance.
+# @exception IOError If the image could not be read.
+
+def open(fp, mode = "r"):
+
+ if mode != "r":
+ raise ValueError("bad mode")
+
+ if type(fp) == type(""):
+ import __builtin__
+ filename = fp
+ fp = __builtin__.open(fp, "rb")
+ else:
+ filename = ""
+
+ try:
+ return GdImageFile(fp, filename)
+ except SyntaxError:
+ raise IOError("cannot identify this image file")
diff --git a/Imaging/PIL/GifImagePlugin.py b/Imaging/PIL/GifImagePlugin.py
new file mode 100644
index 0000000..cce0fe2
--- /dev/null
+++ b/Imaging/PIL/GifImagePlugin.py
@@ -0,0 +1,405 @@
+#
+# The Python Imaging Library.
+# $Id: GifImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# GIF file handling
+#
+# History:
+# 1995-09-01 fl Created
+# 1996-12-14 fl Added interlace support
+# 1996-12-30 fl Added animation support
+# 1997-01-05 fl Added write support, fixed local colour map bug
+# 1997-02-23 fl Make sure to load raster data in getdata()
+# 1997-07-05 fl Support external decoder (0.4)
+# 1998-07-09 fl Handle all modes when saving (0.5)
+# 1998-07-15 fl Renamed offset attribute to avoid name clash
+# 2001-04-16 fl Added rewind support (seek to frame 0) (0.6)
+# 2001-04-17 fl Added palette optimization (0.7)
+# 2002-06-06 fl Added transparency support for save (0.8)
+# 2004-02-24 fl Disable interlacing for small images
+#
+# Copyright (c) 1997-2004 by Secret Labs AB
+# Copyright (c) 1995-2004 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+
+__version__ = "0.9"
+
+
+import Image, ImageFile, ImagePalette
+
+
+# --------------------------------------------------------------------
+# Helpers
+
+def i16(c):
+ return ord(c[0]) + (ord(c[1])<<8)
+
+def o16(i):
+ return chr(i&255) + chr(i>>8&255)
+
+
+# --------------------------------------------------------------------
+# Identify/read GIF files
+
+def _accept(prefix):
+ return prefix[:6] in ["GIF87a", "GIF89a"]
+
+##
+# Image plugin for GIF images. This plugin supports both GIF87 and
+# GIF89 images.
+
+class GifImageFile(ImageFile.ImageFile):
+
+ format = "GIF"
+ format_description = "Compuserve GIF"
+
+ global_palette = None
+
+ def data(self):
+ s = self.fp.read(1)
+ if s and ord(s):
+ return self.fp.read(ord(s))
+ return None
+
+ def _open(self):
+
+ # Screen
+ s = self.fp.read(13)
+ if s[:6] not in ["GIF87a", "GIF89a"]:
+ raise SyntaxError, "not a GIF file"
+
+ self.info["version"] = s[:6]
+
+ self.size = i16(s[6:]), i16(s[8:])
+
+ self.tile = []
+
+ flags = ord(s[10])
+
+ bits = (flags & 7) + 1
+
+ if flags & 128:
+ # get global palette
+ self.info["background"] = ord(s[11])
+ # check if palette contains colour indices
+ p = self.fp.read(3<<bits)
+ for i in range(0, len(p), 3):
+ if not (chr(i/3) == p[i] == p[i+1] == p[i+2]):
+ p = ImagePalette.raw("RGB", p)
+ self.global_palette = self.palette = p
+ break
+
+ self.__fp = self.fp # FIXME: hack
+ self.__rewind = self.fp.tell()
+ self.seek(0) # get ready to read first frame
+
+ def seek(self, frame):
+
+ if frame == 0:
+ # rewind
+ self.__offset = 0
+ self.dispose = None
+ self.__frame = -1
+ self.__fp.seek(self.__rewind)
+
+ if frame != self.__frame + 1:
+ raise ValueError, "cannot seek to frame %d" % frame
+ self.__frame = frame
+
+ self.tile = []
+
+ self.fp = self.__fp
+ if self.__offset:
+ # backup to last frame
+ self.fp.seek(self.__offset)
+ while self.data():
+ pass
+ self.__offset = 0
+
+ if self.dispose:
+ self.im = self.dispose
+ self.dispose = None
+
+ self.palette = self.global_palette
+
+ while 1:
+
+ s = self.fp.read(1)
+ if not s or s == ";":
+ break
+
+ elif s == "!":
+ #
+ # extensions
+ #
+ s = self.fp.read(1)
+ block = self.data()
+ if ord(s) == 249:
+ #
+ # graphic control extension
+ #
+ flags = ord(block[0])
+ if flags & 1:
+ self.info["transparency"] = ord(block[3])
+ self.info["duration"] = i16(block[1:3]) * 10
+ try:
+ # disposal methods
+ if flags & 8:
+ # replace with background colour
+ self.dispose = Image.core.fill("P", self.size,
+ self.info["background"])
+ elif flags & 16:
+ # replace with previous contents
+ self.dispose = self.im.copy()
+ except (AttributeError, KeyError):
+ pass
+ elif ord(s) == 255:
+ #
+ # application extension
+ #
+ self.info["extension"] = block, self.fp.tell()
+ if block[:11] == "NETSCAPE2.0":
+ self.info["loop"] = 1 # FIXME
+ while self.data():
+ pass
+
+ elif s == ",":
+ #
+ # local image
+ #
+ s = self.fp.read(9)
+
+ # extent
+ x0, y0 = i16(s[0:]), i16(s[2:])
+ x1, y1 = x0 + i16(s[4:]), y0 + i16(s[6:])
+ flags = ord(s[8])
+
+ interlace = (flags & 64) != 0
+
+ if flags & 128:
+ bits = (flags & 7) + 1
+ self.palette =\
+ ImagePalette.raw("RGB", self.fp.read(3<<bits))
+
+ # image data
+ bits = ord(self.fp.read(1))
+ self.__offset = self.fp.tell()
+ self.tile = [("gif",
+ (x0, y0, x1, y1),
+ self.__offset,
+ (bits, interlace))]
+ break
+
+ else:
+ pass
+ # raise IOError, "illegal GIF tag `%x`" % ord(s)
+
+ if not self.tile:
+ # self.__fp = None
+ raise EOFError, "no more images in GIF file"
+
+ self.mode = "L"
+ if self.palette:
+ self.mode = "P"
+
+ def tell(self):
+ return self.__frame
+
+
+# --------------------------------------------------------------------
+# Write GIF files
+
+try:
+ import _imaging_gif
+except ImportError:
+ _imaging_gif = None
+
+RAWMODE = {
+ "1": "L",
+ "L": "L",
+ "P": "P",
+}
+
+def _save(im, fp, filename):
+
+ if _imaging_gif:
+ # call external driver
+ try:
+ _imaging_gif.save(im, fp, filename)
+ return
+ except IOError:
+ pass # write uncompressed file
+
+ try:
+ rawmode = RAWMODE[im.mode]
+ imOut = im
+ except KeyError:
+ # convert on the fly (EXPERIMENTAL -- I'm not sure PIL
+ # should automatically convert images on save...)
+ if Image.getmodebase(im.mode) == "RGB":
+ imOut = im.convert("P")
+ rawmode = "P"
+ else:
+ imOut = im.convert("L")
+ rawmode = "L"
+
+ # header
+ for s in getheader(imOut, im.encoderinfo):
+ fp.write(s)
+
+ flags = 0
+
+ try:
+ interlace = im.encoderinfo["interlace"]
+ except KeyError:
+ interlace = 1
+
+ # workaround for @PIL153
+ if min(im.size) < 16:
+ interlace = 0
+
+ if interlace:
+ flags = flags | 64
+
+ try:
+ transparency = im.encoderinfo["transparency"]
+ except KeyError:
+ pass
+ else:
+ # transparency extension block
+ fp.write("!" +
+ chr(249) + # extension intro
+ chr(4) + # length
+ chr(1) + # transparency info present
+ o16(0) + # duration
+ chr(int(transparency)) # transparency index
+ + chr(0))
+
+ # local image header
+ fp.write("," +
+ o16(0) + o16(0) + # bounding box
+ o16(im.size[0]) + # size
+ o16(im.size[1]) +
+ chr(flags) + # flags
+ chr(8)) # bits
+
+ imOut.encoderconfig = (8, interlace)
+
+ ImageFile._save(imOut, fp, [("gif", (0,0)+im.size, 0, rawmode)])
+
+ fp.write("\0") # end of image data
+
+ fp.write(";") # end of file
+
+ try:
+ fp.flush()
+ except: pass
+
+def _save_netpbm(im, fp, filename):
+
+ #
+ # If you need real GIF compression and/or RGB quantization, you
+ # can use the external NETPBM/PBMPLUS utilities. See comments
+ # below for information on how to enable this.
+
+ import os
+ file = im._dump()
+ if im.mode != "RGB":
+ os.system("ppmtogif %s >%s" % (file, filename))
+ else:
+ os.system("ppmquant 256 %s | ppmtogif >%s" % (file, filename))
+ try: os.unlink(file)
+ except: pass
+
+
+# --------------------------------------------------------------------
+# GIF utilities
+
+def getheader(im, info=None):
+ """Return a list of strings representing a GIF header"""
+
+ optimize = info and info.get("optimize", 0)
+
+ s = [
+ "GIF87a" + # magic
+ o16(im.size[0]) + # size
+ o16(im.size[1]) +
+ chr(7 + 128) + # flags: bits + palette
+ chr(0) + # background
+ chr(0) # reserved/aspect
+ ]
+
+ if optimize:
+ # minimize color palette
+ i = 0
+ maxcolor = 0
+ for count in im.histogram():
+ if count:
+ maxcolor = i
+ i = i + 1
+ else:
+ maxcolor = 256
+
+ # global palette
+ if im.mode == "P":
+ # colour palette
+ s.append(im.im.getpalette("RGB")[:maxcolor*3])
+ else:
+ # greyscale
+ for i in range(maxcolor):
+ s.append(chr(i) * 3)
+
+ return s
+
+def getdata(im, offset = (0, 0), **params):
+ """Return a list of strings representing this image.
+ The first string is a local image header, the rest contains
+ encoded image data."""
+
+ class collector:
+ data = []
+ def write(self, data):
+ self.data.append(data)
+
+ im.load() # make sure raster data is available
+
+ fp = collector()
+
+ try:
+ im.encoderinfo = params
+
+ # local image header
+ fp.write("," +
+ o16(offset[0]) + # offset
+ o16(offset[1]) +
+ o16(im.size[0]) + # size
+ o16(im.size[1]) +
+ chr(0) + # flags
+ chr(8)) # bits
+
+ ImageFile._save(im, fp, [("gif", (0,0)+im.size, 0, RAWMODE[im.mode])])
+
+ fp.write("\0") # end of image data
+
+ finally:
+ del im.encoderinfo
+
+ return fp.data
+
+
+# --------------------------------------------------------------------
+# Registry
+
+Image.register_open(GifImageFile.format, GifImageFile, _accept)
+Image.register_save(GifImageFile.format, _save)
+Image.register_extension(GifImageFile.format, ".gif")
+Image.register_mime(GifImageFile.format, "image/gif")
+
+#
+# Uncomment the following line if you wish to use NETPBM/PBMPLUS
+# instead of the built-in "uncompressed" GIF encoder
+
+# Image.register_save(GifImageFile.format, _save_netpbm)
diff --git a/Imaging/PIL/GimpGradientFile.py b/Imaging/PIL/GimpGradientFile.py
new file mode 100644
index 0000000..e246d6d
--- /dev/null
+++ b/Imaging/PIL/GimpGradientFile.py
@@ -0,0 +1,124 @@
+#
+# Python Imaging Library
+# $Id: GimpGradientFile.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# stuff to read (and render) GIMP gradient files
+#
+# History:
+# 97-08-23 fl Created
+#
+# Copyright (c) Secret Labs AB 1997.
+# Copyright (c) Fredrik Lundh 1997.
+#
+# See the README file for information on usage and redistribution.
+#
+
+from math import pi, log, sin, sqrt
+import string
+
+# --------------------------------------------------------------------
+# Stuff to translate curve segments to palette values (derived from
+# the corresponding code in GIMP, written by Federico Mena Quintero.
+# See the GIMP distribution for more information.)
+#
+
+EPSILON = 1e-10
+
+def linear(middle, pos):
+ if pos <= middle:
+ if middle < EPSILON:
+ return 0.0
+ else:
+ return 0.5 * pos / middle
+ else:
+ pos = pos - middle
+ middle = 1.0 - middle
+ if middle < EPSILON:
+ return 1.0
+ else:
+ return 0.5 + 0.5 * pos / middle
+
+def curved(middle, pos):
+ return pos ** (log(0.5) / log(max(middle, EPSILON)))
+
+def sine(middle, pos):
+ return (sin((-pi / 2.0) + pi * linear(middle, pos)) + 1.0) / 2.0
+
+def sphere_increasing(middle, pos):
+ return sqrt(1.0 - (linear(middle, pos) - 1.0) ** 2)
+
+def sphere_decreasing(middle, pos):
+ return 1.0 - sqrt(1.0 - linear(middle, pos) ** 2)
+
+SEGMENTS = [ linear, curved, sine, sphere_increasing, sphere_decreasing ]
+
+class GradientFile:
+
+ gradient = None
+
+ def getpalette(self, entries = 256):
+
+ palette = []
+
+ ix = 0
+ x0, x1, xm, rgb0, rgb1, segment = self.gradient[ix]
+
+ for i in range(entries):
+
+ x = i / float(entries-1)
+
+ while x1 < x:
+ ix = ix + 1
+ x0, x1, xm, rgb0, rgb1, segment = self.gradient[ix]
+
+ w = x1 - x0
+
+ if w < EPSILON:
+ scale = segment(0.5, 0.5)
+ else:
+ scale = segment((xm - x0) / w, (x - x0) / w)
+
+ # expand to RGBA
+ r = chr(int(255 * ((rgb1[0] - rgb0[0]) * scale + rgb0[0]) + 0.5))
+ g = chr(int(255 * ((rgb1[1] - rgb0[1]) * scale + rgb0[1]) + 0.5))
+ b = chr(int(255 * ((rgb1[2] - rgb0[2]) * scale + rgb0[2]) + 0.5))
+ a = chr(int(255 * ((rgb1[3] - rgb0[3]) * scale + rgb0[3]) + 0.5))
+
+ # add to palette
+ palette.append(r + g + b + a)
+
+ return string.join(palette, ""), "RGBA"
+
+##
+# File handler for GIMP's gradient format.
+
+class GimpGradientFile(GradientFile):
+
+ def __init__(self, fp):
+
+ if fp.readline()[:13] != "GIMP Gradient":
+ raise SyntaxError, "not a GIMP gradient file"
+
+ count = int(fp.readline())
+
+ gradient = []
+
+ for i in range(count):
+
+ s = string.split(fp.readline())
+ w = map(float, s[:11])
+
+ x0, x1 = w[0], w[2]
+ xm = w[1]
+ rgb0 = w[3:7]
+ rgb1 = w[7:11]
+
+ segment = SEGMENTS[int(s[11])]
+ cspace = int(s[12])
+
+ if cspace != 0:
+ raise IOError, "cannot handle HSV colour space"
+
+ gradient.append((x0, x1, xm, rgb0, rgb1, segment))
+
+ self.gradient = gradient
diff --git a/Imaging/PIL/GimpPaletteFile.py b/Imaging/PIL/GimpPaletteFile.py
new file mode 100644
index 0000000..3939147
--- /dev/null
+++ b/Imaging/PIL/GimpPaletteFile.py
@@ -0,0 +1,61 @@
+#
+# Python Imaging Library
+# $Id: GimpPaletteFile.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# stuff to read GIMP palette files
+#
+# History:
+# 1997-08-23 fl Created
+# 2004-09-07 fl Support GIMP 2.0 palette files.
+#
+# Copyright (c) Secret Labs AB 1997-2004. All rights reserved.
+# Copyright (c) Fredrik Lundh 1997-2004.
+#
+# See the README file for information on usage and redistribution.
+#
+
+import re, string
+
+##
+# File handler for GIMP's palette format.
+
+class GimpPaletteFile:
+
+ rawmode = "RGB"
+
+ def __init__(self, fp):
+
+ self.palette = map(lambda i: chr(i)*3, range(256))
+
+ if fp.readline()[:12] != "GIMP Palette":
+ raise SyntaxError, "not a GIMP palette file"
+
+ i = 0
+
+ while i <= 255:
+
+ s = fp.readline()
+
+ if not s:
+ break
+ # skip fields and comment lines
+ if re.match("\w+:|#", s):
+ continue
+ if len(s) > 100:
+ raise SyntaxError, "bad palette file"
+
+ v = tuple(map(int, string.split(s)[:3]))
+ if len(v) != 3:
+ raise ValueError, "bad palette entry"
+
+ if 0 <= i <= 255:
+ self.palette[i] = chr(v[0]) + chr(v[1]) + chr(v[2])
+
+ i = i + 1
+
+ self.palette = string.join(self.palette, "")
+
+
+ def getpalette(self):
+
+ return self.palette, self.rawmode
diff --git a/Imaging/PIL/GribStubImagePlugin.py b/Imaging/PIL/GribStubImagePlugin.py
new file mode 100644
index 0000000..73d5404
--- /dev/null
+++ b/Imaging/PIL/GribStubImagePlugin.py
@@ -0,0 +1,68 @@
+#
+# The Python Imaging Library
+# $Id: GribStubImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# GRIB stub adapter
+#
+# Copyright (c) 1996-2003 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image, ImageFile
+
+_handler = None
+
+##
+# Install application-specific GRIB image handler.
+#
+# @param handler Handler object.
+
+def register_handler(handler):
+ global _handler
+ _handler = handler
+
+# --------------------------------------------------------------------
+# Image adapter
+
+def _accept(prefix):
+ return prefix[0:4] == "GRIB" and prefix[7] == chr(1)
+
+class GribStubImageFile(ImageFile.StubImageFile):
+
+ format = "GRIB"
+ format_description = "GRIB"
+
+ def _open(self):
+
+ offset = self.fp.tell()
+
+ if not _accept(self.fp.read(8)):
+ raise SyntaxError("Not a GRIB file")
+
+ self.fp.seek(offset)
+
+ # make something up
+ self.mode = "F"
+ self.size = 1, 1
+
+ loader = self._load()
+ if loader:
+ loader.open(self)
+
+ def _load(self):
+ return _handler
+
+def _save(im, fp, filename):
+ if _handler is None or not hasattr("_handler", "save"):
+ raise IOError("GRIB save handler not installed")
+ _handler.save(im, fp, filename)
+
+
+# --------------------------------------------------------------------
+# Registry
+
+Image.register_open(GribStubImageFile.format, GribStubImageFile, _accept)
+Image.register_save(GribStubImageFile.format, _save)
+
+Image.register_extension(GribStubImageFile.format, ".grib")
diff --git a/Imaging/PIL/Hdf5StubImagePlugin.py b/Imaging/PIL/Hdf5StubImagePlugin.py
new file mode 100644
index 0000000..31d4f6e
--- /dev/null
+++ b/Imaging/PIL/Hdf5StubImagePlugin.py
@@ -0,0 +1,70 @@
+#
+# The Python Imaging Library
+# $Id: Hdf5StubImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# HDF5 stub adapter
+#
+# Copyright (c) 2000-2003 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image, ImageFile
+
+_handler = None
+
+##
+# Install application-specific HDF5 image handler.
+#
+# @param handler Handler object.
+
+def register_handler(handler):
+ global _handler
+ _handler = handler
+
+# --------------------------------------------------------------------
+# Image adapter
+
+def _accept(prefix):
+ return prefix[:8] == "\x89HDF\r\n\x1a\n"
+
+class HDF5StubImageFile(ImageFile.StubImageFile):
+
+ format = "HDF5"
+ format_description = "HDF5"
+
+ def _open(self):
+
+ offset = self.fp.tell()
+
+ if not _accept(self.fp.read(8)):
+ raise SyntaxError("Not an HDF file")
+
+ self.fp.seek(offset)
+
+ # make something up
+ self.mode = "F"
+ self.size = 1, 1
+
+ loader = self._load()
+ if loader:
+ loader.open(self)
+
+ def _load(self):
+ return _handler
+
+
+def _save(im, fp, filename):
+ if _handler is None or not hasattr("_handler", "save"):
+ raise IOError("HDF5 save handler not installed")
+ _handler.save(im, fp, filename)
+
+
+# --------------------------------------------------------------------
+# Registry
+
+Image.register_open(HDF5StubImageFile.format, HDF5StubImageFile, _accept)
+Image.register_save(HDF5StubImageFile.format, _save)
+
+Image.register_extension(HDF5StubImageFile.format, ".h5")
+Image.register_extension(HDF5StubImageFile.format, ".hdf")
diff --git a/Imaging/PIL/IcnsImagePlugin.py b/Imaging/PIL/IcnsImagePlugin.py
new file mode 100644
index 0000000..a85695d
--- /dev/null
+++ b/Imaging/PIL/IcnsImagePlugin.py
@@ -0,0 +1,211 @@
+#
+# The Python Imaging Library.
+# $Id: ImImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# Mac OS X icns file decoder, based on icns.py by Bob Ippolito.
+#
+# history:
+# 2004-10-09 fl Turned into a PIL plugin; removed 2.3 dependencies.
+#
+# Copyright (c) 2004 by Bob Ippolito.
+# Copyright (c) 2004 by Secret Labs.
+# Copyright (c) 2004 by Fredrik Lundh.
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image, ImageFile
+import string, struct
+
+HEADERSIZE = 8
+
+def nextheader(fobj):
+ return struct.unpack('>4sI', fobj.read(HEADERSIZE))
+
+def read_32t(fobj, (start, length), (width, height)):
+ # The 128x128 icon seems to have an extra header for some reason.
+ fobj.seek(start)
+ sig = fobj.read(4)
+ if sig != '\x00\x00\x00\x00':
+ raise SyntaxError, 'Unknown signature, expecting 0x00000000'
+ return read_32(fobj, (start + 4, length - 4), (width, height))
+
+def read_32(fobj, (start, length), size):
+ """
+ Read a 32bit RGB icon resource. Seems to be either uncompressed or
+ an RLE packbits-like scheme.
+ """
+ fobj.seek(start)
+ sizesq = size[0] * size[1]
+ if length == sizesq * 3:
+ # uncompressed ("RGBRGBGB")
+ indata = fobj.read(length)
+ im = Image.frombuffer("RGB", size, indata, "raw", "RGB", 0, 1)
+ else:
+ # decode image
+ im = Image.new("RGB", size, None)
+ for band_ix in range(3):
+ data = []
+ bytesleft = sizesq
+ while bytesleft > 0:
+ byte = fobj.read(1)
+ if not byte:
+ break
+ byte = ord(byte)
+ if byte & 0x80:
+ blocksize = byte - 125
+ byte = fobj.read(1)
+ for i in range(blocksize):
+ data.append(byte)
+ else:
+ blocksize = byte + 1
+ data.append(fobj.read(blocksize))
+ bytesleft = bytesleft - blocksize
+ if bytesleft <= 0:
+ break
+ if bytesleft != 0:
+ raise SyntaxError(
+ "Error reading %r channel [%r]" % (channel, bytesleft)
+ )
+ band = Image.frombuffer(
+ "L", size, string.join(data, ""), "raw", "L", 0, 1
+ )
+ im.im.putband(band.im, band_ix)
+ return {"RGB": im}
+
+def read_mk(fobj, (start, length), size):
+ # Alpha masks seem to be uncompressed
+ fobj.seek(start)
+ band = Image.frombuffer(
+ "L", size, fobj.read(size[0]*size[1]), "raw", "L", 0, 1
+ )
+ return {"A": band}
+
+class IcnsFile:
+
+ SIZES = {
+ (128, 128): [
+ ('it32', read_32t),
+ ('t8mk', read_mk),
+ ],
+ (48, 48): [
+ ('ih32', read_32),
+ ('h8mk', read_mk),
+ ],
+ (32, 32): [
+ ('il32', read_32),
+ ('l8mk', read_mk),
+ ],
+ (16, 16): [
+ ('is32', read_32),
+ ('s8mk', read_mk),
+ ],
+ }
+
+ def __init__(self, fobj):
+ """
+ fobj is a file-like object as an icns resource
+ """
+ # signature : (start, length)
+ self.dct = dct = {}
+ self.fobj = fobj
+ sig, filesize = nextheader(fobj)
+ if sig != 'icns':
+ raise SyntaxError, 'not an icns file'
+ i = HEADERSIZE
+ while i < filesize:
+ sig, blocksize = nextheader(fobj)
+ i = i + HEADERSIZE
+ blocksize = blocksize - HEADERSIZE
+ dct[sig] = (i, blocksize)
+ fobj.seek(blocksize, 1)
+ i = i + blocksize
+
+ def itersizes(self):
+ sizes = []
+ for size, fmts in self.SIZES.items():
+ for (fmt, reader) in fmts:
+ if self.dct.has_key(fmt):
+ sizes.append(size)
+ break
+ return sizes
+
+ def bestsize(self):
+ sizes = self.itersizes()
+ if not sizes:
+ raise SyntaxError, "No 32bit icon resources found"
+ return max(sizes)
+
+ def dataforsize(self, size):
+ """
+ Get an icon resource as {channel: array}. Note that
+ the arrays are bottom-up like windows bitmaps and will likely
+ need to be flipped or transposed in some way.
+ """
+ dct = {}
+ for code, reader in self.SIZES[size]:
+ desc = self.dct.get(code)
+ if desc is not None:
+ dct.update(reader(self.fobj, desc, size))
+ return dct
+
+ def getimage(self, size=None):
+ if size is None:
+ size = self.bestsize()
+ channels = self.dataforsize(size)
+ im = channels.get("RGB").copy()
+ try:
+ im.putalpha(channels["A"])
+ except KeyError:
+ pass
+ return im
+
+##
+# Image plugin for Mac OS icons.
+
+class IcnsImageFile(ImageFile.ImageFile):
+ """
+ PIL read-only image support for Mac OS .icns files.
+ Chooses the best resolution, but will possibly load
+ a different size image if you mutate the size attribute
+ before calling 'load'.
+
+ The info dictionary has a key 'sizes' that is a list
+ of sizes that the icns file has.
+ """
+
+ format = "ICNS"
+ format_description = "Mac OS icns resource"
+
+ def _open(self):
+ self.icns = IcnsFile(self.fp)
+ self.mode = 'RGBA'
+ self.size = self.icns.bestsize()
+ self.info['sizes'] = self.icns.itersizes()
+ # Just use this to see if it's loaded or not yet.
+ self.tile = ('',)
+
+ def load(self):
+ Image.Image.load(self)
+ if not self.tile:
+ return
+ self.load_prepare()
+ # This is likely NOT the best way to do it, but whatever.
+ im = self.icns.getimage(self.size)
+ self.im = im.im
+ self.mode = im.mode
+ self.size = im.size
+ self.fp = None
+ self.icns = None
+ self.tile = ()
+ self.load_end()
+
+
+Image.register_open("ICNS", IcnsImageFile, lambda x: x[:4] == 'icns')
+Image.register_extension("ICNS", '.icns')
+
+if __name__ == '__main__':
+ import os, sys
+ im = Image.open(open(sys.argv[1], "rb"))
+ im.save("out.png")
+ os.startfile("out.png")
diff --git a/Imaging/PIL/IcoImagePlugin.py b/Imaging/PIL/IcoImagePlugin.py
new file mode 100644
index 0000000..5cdd284
--- /dev/null
+++ b/Imaging/PIL/IcoImagePlugin.py
@@ -0,0 +1,88 @@
+#
+# The Python Imaging Library.
+# $Id: IcoImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# Windows Icon support for PIL
+#
+# Notes:
+# uses BmpImagePlugin.py to read the bitmap data.
+#
+# History:
+# 96-05-27 fl Created
+#
+# Copyright (c) Secret Labs AB 1997.
+# Copyright (c) Fredrik Lundh 1996.
+#
+# See the README file for information on usage and redistribution.
+#
+
+
+__version__ = "0.1"
+
+import string
+
+import Image, BmpImagePlugin
+
+
+#
+# --------------------------------------------------------------------
+
+def i16(c):
+ return ord(c[0]) + (ord(c[1])<<8)
+
+def i32(c):
+ return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
+
+
+def _accept(prefix):
+ return prefix[:4] == "\0\0\1\0"
+
+##
+# Image plugin for Windows Icon files.
+
+class IcoImageFile(BmpImagePlugin.BmpImageFile):
+
+ format = "ICO"
+ format_description = "Windows Icon"
+
+ def _open(self):
+
+ # check magic
+ s = self.fp.read(6)
+ if not _accept(s):
+ raise SyntaxError, "not an ICO file"
+
+ # pick the largest icon in the file
+ m = ""
+ 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
+ #print "width", ord(s[0])
+ #print "height", ord(s[1])
+ #print "colors", ord(s[2])
+ #print "reserved", ord(s[3])
+ #print "planes", i16(s[4:])
+ #print "bitcount", i16(s[6:])
+ #print "bytes", i32(s[8:])
+ #print "offset", i32(s[12:])
+
+ # load as bitmap
+ self._bitmap(i32(m[12:]))
+
+ # patch up the bitmap height
+ self.size = self.size[0], self.size[1]/2
+ d, e, o, a = self.tile[0]
+ self.tile[0] = d, (0,0)+self.size, o, a
+
+ return
+
+
+#
+# --------------------------------------------------------------------
+
+Image.register_open("ICO", IcoImageFile, _accept)
+
+Image.register_extension("ICO", ".ico")
diff --git a/Imaging/PIL/ImImagePlugin.py b/Imaging/PIL/ImImagePlugin.py
new file mode 100644
index 0000000..17b8c0e
--- /dev/null
+++ b/Imaging/PIL/ImImagePlugin.py
@@ -0,0 +1,335 @@
+#
+# The Python Imaging Library.
+# $Id: ImImagePlugin.py 2285 2005-02-07 23:52:14Z fredrik $
+#
+# IFUNC IM file handling for PIL
+#
+# history:
+# 1995-09-01 fl Created.
+# 1997-01-03 fl Save palette images
+# 1997-01-08 fl Added sequence support
+# 1997-01-23 fl Added P and RGB save support
+# 1997-05-31 fl Read floating point images
+# 1997-06-22 fl Save floating point images
+# 1997-08-27 fl Read and save 1-bit images
+# 1998-06-25 fl Added support for RGB+LUT images
+# 1998-07-02 fl Added support for YCC images
+# 1998-07-15 fl Renamed offset attribute to avoid name clash
+# 1998-12-29 fl Added I;16 support
+# 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.7)
+# 2003-09-26 fl Added LA/PA support
+#
+# Copyright (c) 1997-2003 by Secret Labs AB.
+# Copyright (c) 1995-2001 by Fredrik Lundh.
+#
+# See the README file for information on usage and redistribution.
+#
+
+
+__version__ = "0.7"
+
+import re, string
+import Image, ImageFile, ImagePalette
+
+
+# --------------------------------------------------------------------
+# Standard tags
+
+COMMENT = "Comment"
+DATE = "Date"
+EQUIPMENT = "Digitalization equipment"
+FRAMES = "File size (no of images)"
+LUT = "Lut"
+NAME = "Name"
+SCALE = "Scale (x,y)"
+SIZE = "Image size (x*y)"
+MODE = "Image type"
+
+TAGS = { COMMENT:0, DATE:0, EQUIPMENT:0, FRAMES:0, LUT:0, NAME:0,
+ SCALE:0, SIZE:0, MODE:0 }
+
+OPEN = {
+ # ifunc93/p3cfunc formats
+ "0 1 image": ("1", "1"),
+ "L 1 image": ("1", "1"),
+ "Greyscale image": ("L", "L"),
+ "Grayscale image": ("L", "L"),
+ "RGB image": ("RGB", "RGB;L"),
+ "RLB image": ("RGB", "RLB"),
+ "RYB image": ("RGB", "RLB"),
+ "B1 image": ("1", "1"),
+ "B2 image": ("P", "P;2"),
+ "B4 image": ("P", "P;4"),
+ "X 24 image": ("RGB", "RGB"),
+ "L 32 S image": ("I", "I;32"),
+ "L 32 F image": ("F", "F;32"),
+ # old p3cfunc formats
+ "RGB3 image": ("RGB", "RGB;T"),
+ "RYB3 image": ("RGB", "RYB;T"),
+ # extensions
+ "LA image": ("LA", "LA;L"),
+ "RGBA image": ("RGBA", "RGBA;L"),
+ "RGBX image": ("RGBX", "RGBX;L"),
+ "CMYK image": ("CMYK", "CMYK;L"),
+ "YCC image": ("YCbCr", "YCbCr;L"),
+}
+
+# ifunc95 extensions
+for i in ["8", "8S", "16", "16S", "32", "32F"]:
+ OPEN["L %s image" % i] = ("F", "F;%s" % i)
+ OPEN["L*%s image" % i] = ("F", "F;%s" % i)
+for i in ["16", "16B"]:
+ OPEN["L %s image" % i] = ("I;%s" % i, "I;%s" % i)
+ OPEN["L*%s image" % i] = ("I;%s" % i, "I;%s" % i)
+for i in ["32S"]:
+ OPEN["L %s image" % i] = ("I", "I;%s" % i)
+ OPEN["L*%s image" % i] = ("I", "I;%s" % i)
+for i in range(2, 33):
+ OPEN["L*%s image" % i] = ("F", "F;%s" % i)
+
+
+# --------------------------------------------------------------------
+# Read IM directory
+
+split = re.compile(r"^([A-Za-z][^:]*):[ \t]*(.*)[ \t]*$")
+
+def number(s):
+ try:
+ return int(s)
+ except ValueError:
+ return float(s)
+
+##
+# Image plugin for the IFUNC IM file format.
+
+class ImImageFile(ImageFile.ImageFile):
+
+ format = "IM"
+ format_description = "IFUNC Image Memory"
+
+ def _open(self):
+
+ # Quick rejection: if there's not an LF among the first
+ # 100 bytes, this is (probably) not a text header.
+
+ if not "\n" in self.fp.read(100):
+ raise SyntaxError, "not an IM file"
+ self.fp.seek(0)
+
+ n = 0
+
+ # Default values
+ self.info[MODE] = "L"
+ self.info[SIZE] = (512, 512)
+ self.info[FRAMES] = 1
+
+ self.rawmode = "L"
+
+ while 1:
+
+ s = self.fp.read(1)
+
+ # Some versions of IFUNC uses \n\r instead of \r\n...
+ if s == "\r":
+ continue
+
+ if not s or s[0] == chr(0) or s[0] == chr(26):
+ break
+
+ # FIXME: this may read whole file if not a text file
+ s = s + self.fp.readline()
+
+ if len(s) > 100:
+ raise SyntaxError, "not an IM file"
+
+ if s[-2:] == '\r\n':
+ s = s[:-2]
+ elif s[-1:] == '\n':
+ s = s[:-1]
+
+ try:
+ m = split.match(s)
+ except re.error, v:
+ raise SyntaxError, "not an IM file"
+
+ if m:
+
+ k, v = m.group(1,2)
+
+ # Convert value as appropriate
+ if k in [FRAMES, SCALE, SIZE]:
+ v = string.replace(v, "*", ",")
+ v = tuple(map(number, string.split(v, ",")))
+ if len(v) == 1:
+ v = v[0]
+ elif k == MODE and OPEN.has_key(v):
+ v, self.rawmode = OPEN[v]
+
+ # Add to dictionary. Note that COMMENT tags are
+ # combined into a list of strings.
+ if k == COMMENT:
+ if self.info.has_key(k):
+ self.info[k].append(v)
+ else:
+ self.info[k] = [v]
+ else:
+ self.info[k] = v
+
+ if TAGS.has_key(k):
+ n = n + 1
+
+ else:
+
+ raise SyntaxError, "Syntax error in IM header: " + s
+
+ if not n:
+ raise SyntaxError, "Not an IM file"
+
+ # Basic attributes
+ self.size = self.info[SIZE]
+ self.mode = self.info[MODE]
+
+ # Skip forward to start of image data
+ while s and s[0] != chr(26):
+ s = self.fp.read(1)
+ if not s:
+ raise SyntaxError, "File truncated"
+
+ if self.info.has_key(LUT):
+ # convert lookup table to palette or lut attribute
+ palette = self.fp.read(768)
+ greyscale = 1 # greyscale palette
+ linear = 1 # linear greyscale palette
+ for i in range(256):
+ if palette[i] == palette[i+256] == palette[i+512]:
+ if palette[i] != chr(i):
+ linear = 0
+ else:
+ greyscale = 0
+ if self.mode == "L" or self.mode == "LA":
+ if greyscale:
+ if not linear:
+ self.lut = map(ord, palette[:256])
+ else:
+ if self.mode == "L":
+ self.mode = self.rawmode = "P"
+ elif self.mode == "LA":
+ self.mode = self.rawmode = "PA"
+ self.palette = ImagePalette.raw("RGB;L", palette)
+ elif self.mode == "RGB":
+ if not greyscale or not linear:
+ self.lut = map(ord, palette)
+
+ self.frame = 0
+
+ self.__offset = offs = self.fp.tell()
+
+ self.__fp = self.fp # FIXME: hack
+
+ if self.rawmode[:2] == "F;":
+
+ # ifunc95 formats
+ try:
+ # use bit decoder (if necessary)
+ bits = int(self.rawmode[2:])
+ if bits not in [8, 16, 32]:
+ self.tile = [("bit", (0,0)+self.size, offs,
+ (bits, 8, 3, 0, -1))]
+ return
+ except ValueError:
+ pass
+
+ if self.rawmode in ["RGB;T", "RYB;T"]:
+ # Old LabEye/3PC files. Would be very surprised if anyone
+ # ever stumbled upon such a file ;-)
+ size = self.size[0] * self.size[1]
+ self.tile = [("raw", (0,0)+self.size, offs, ("G", 0, -1)),
+ ("raw", (0,0)+self.size, offs+size, ("R", 0, -1)),
+ ("raw", (0,0)+self.size, offs+2*size, ("B", 0, -1))]
+ else:
+ # LabEye/IFUNC files
+ self.tile = [("raw", (0,0)+self.size, offs, (self.rawmode, 0, -1))]
+
+ def seek(self, frame):
+
+ if frame < 0 or frame >= self.info[FRAMES]:
+ raise EOFError, "seek outside sequence"
+
+ if self.frame == frame:
+ return
+
+ self.frame = frame
+
+ if self.mode == "1":
+ bits = 1
+ else:
+ bits = 8 * len(self.mode)
+
+ size = ((self.size[0] * bits + 7) / 8) * self.size[1]
+ offs = self.__offset + frame * size
+
+ self.fp = self.__fp
+
+ self.tile = [("raw", (0,0)+self.size, offs, (self.rawmode, 0, -1))]
+
+ def tell(self):
+
+ return self.frame
+
+#
+# --------------------------------------------------------------------
+# Save IM files
+
+SAVE = {
+ # mode: (im type, raw mode)
+ "1": ("0 1", "1"),
+ "L": ("Greyscale", "L"),
+ "LA": ("LA", "LA;L"),
+ "P": ("Greyscale", "P"),
+ "PA": ("LA", "PA;L"),
+ "I": ("L 32S", "I;32S"),
+ "I;16": ("L 16", "I;16"),
+ "I;16B": ("L 16B", "I;16B"),
+ "F": ("L 32F", "F;32F"),
+ "RGB": ("RGB", "RGB;L"),
+ "RGBA": ("RGBA", "RGBA;L"),
+ "RGBX": ("RGBX", "RGBX;L"),
+ "CMYK": ("CMYK", "CMYK;L"),
+ "YCbCr": ("YCC", "YCbCr;L")
+}
+
+def _save(im, fp, filename, check=0):
+
+ try:
+ type, rawmode = SAVE[im.mode]
+ except KeyError:
+ raise ValueError, "Cannot save %s images as IM" % im.mode
+
+ try:
+ frames = im.encoderinfo["frames"]
+ except KeyError:
+ frames = 1
+
+ if check:
+ return check
+
+ fp.write("Image type: %s image\r\n" % type)
+ if filename:
+ fp.write("Name: %s\r\n" % filename)
+ fp.write("Image size (x*y): %d*%d\r\n" % im.size)
+ fp.write("File size (no of images): %d\r\n" % frames)
+ if im.mode == "P":
+ fp.write("Lut: 1\r\n")
+ fp.write("\000" * (511-fp.tell()) + "\032")
+ if im.mode == "P":
+ fp.write(im.im.getpalette("RGB", "RGB;L")) # 768 bytes
+ ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, 0, -1))])
+
+#
+# --------------------------------------------------------------------
+# Registry
+
+Image.register_open("IM", ImImageFile)
+Image.register_save("IM", _save)
+
+Image.register_extension("IM", ".im")
diff --git a/Imaging/PIL/Image.py b/Imaging/PIL/Image.py
new file mode 100644
index 0000000..04ed316
--- /dev/null
+++ b/Imaging/PIL/Image.py
@@ -0,0 +1,2093 @@
+#
+# The Python Imaging Library.
+# $Id: Image.py 2933 2006-12-03 12:08:22Z fredrik $
+#
+# the Image class wrapper
+#
+# partial release history:
+# 1995-09-09 fl Created
+# 1996-03-11 fl PIL release 0.0 (proof of concept)
+# 1996-04-30 fl PIL release 0.1b1
+# 1999-07-28 fl PIL release 1.0 final
+# 2000-06-07 fl PIL release 1.1
+# 2000-10-20 fl PIL release 1.1.1
+# 2001-05-07 fl PIL release 1.1.2
+# 2002-03-15 fl PIL release 1.1.3
+# 2003-05-10 fl PIL release 1.1.4
+# 2005-03-28 fl PIL release 1.1.5
+# 2006-12-02 fl PIL release 1.1.6
+#
+# Copyright (c) 1997-2006 by Secret Labs AB. All rights reserved.
+# Copyright (c) 1995-2006 by Fredrik Lundh.
+#
+# See the README file for information on usage and redistribution.
+#
+
+VERSION = "1.1.6"
+
+try:
+ import warnings
+except ImportError:
+ warnings = None
+
+class _imaging_not_installed:
+ # module placeholder
+ def __getattr__(self, id):
+ raise ImportError("The _imaging C module is not installed")
+
+try:
+ # give Tk a chance to set up the environment, in case we're
+ # using an _imaging module linked against libtcl/libtk (use
+ # __import__ to hide this from naive packagers; we don't really
+ # depend on Tk unless ImageTk is used, and that module already
+ # imports Tkinter)
+ __import__("FixTk")
+except ImportError:
+ pass
+
+try:
+ # If the _imaging C module is not present, you can still use
+ # the "open" function to identify files, but you cannot load
+ # them. Note that other modules should not refer to _imaging
+ # directly; import Image and use the Image.core variable instead.
+ import _imaging
+ core = _imaging
+ del _imaging
+except ImportError, v:
+ core = _imaging_not_installed()
+ if str(v)[:20] == "Module use of python" and warnings:
+ # The _imaging C module is present, but not compiled for
+ # the right version (windows only). Print a warning, if
+ # possible.
+ warnings.warn(
+ "The _imaging extension was built for another version "
+ "of Python; most PIL functions will be disabled",
+ RuntimeWarning
+ )
+
+import ImageMode
+import ImagePalette
+
+import os, string, sys
+
+# type stuff
+from types import IntType, StringType, TupleType
+
+try:
+ UnicodeStringType = type(unicode(""))
+ ##
+ # (Internal) Checks if an object is a string. If the current
+ # Python version supports Unicode, this checks for both 8-bit
+ # and Unicode strings.
+ def isStringType(t):
+ return isinstance(t, StringType) or isinstance(t, UnicodeStringType)
+except NameError:
+ def isStringType(t):
+ return isinstance(t, StringType)
+
+##
+# (Internal) Checks if an object is a tuple.
+
+def isTupleType(t):
+ return isinstance(t, TupleType)
+
+##
+# (Internal) Checks if an object is an image object.
+
+def isImageType(t):
+ return hasattr(t, "im")
+
+##
+# (Internal) Checks if an object is a string, and that it points to a
+# directory.
+
+def isDirectory(f):
+ return isStringType(f) and os.path.isdir(f)
+
+from operator import isNumberType, isSequenceType
+
+#
+# Debug level
+
+DEBUG = 0
+
+#
+# Constants (also defined in _imagingmodule.c!)
+
+NONE = 0
+
+# transpose
+FLIP_LEFT_RIGHT = 0
+FLIP_TOP_BOTTOM = 1
+ROTATE_90 = 2
+ROTATE_180 = 3
+ROTATE_270 = 4
+
+# transforms
+AFFINE = 0
+EXTENT = 1
+PERSPECTIVE = 2
+QUAD = 3
+MESH = 4
+
+# resampling filters
+NONE = 0
+NEAREST = 0
+ANTIALIAS = 1 # 3-lobed lanczos
+LINEAR = BILINEAR = 2
+CUBIC = BICUBIC = 3
+
+# dithers
+NONE = 0
+NEAREST = 0
+ORDERED = 1 # Not yet implemented
+RASTERIZE = 2 # Not yet implemented
+FLOYDSTEINBERG = 3 # default
+
+# palettes/quantizers
+WEB = 0
+ADAPTIVE = 1
+
+# categories
+NORMAL = 0
+SEQUENCE = 1
+CONTAINER = 2
+
+# --------------------------------------------------------------------
+# Registries
+
+ID = []
+OPEN = {}
+MIME = {}
+SAVE = {}
+EXTENSION = {}
+
+# --------------------------------------------------------------------
+# Modes supported by this version
+
+_MODEINFO = {
+ # NOTE: this table will be removed in future versions. use
+ # getmode* functions or ImageMode descriptors instead.
+
+ # official modes
+ "1": ("L", "L", ("1",)),
+ "L": ("L", "L", ("L",)),
+ "I": ("L", "I", ("I",)),
+ "F": ("L", "F", ("F",)),
+ "P": ("RGB", "L", ("P",)),
+ "RGB": ("RGB", "L", ("R", "G", "B")),
+ "RGBX": ("RGB", "L", ("R", "G", "B", "X")),
+ "RGBA": ("RGB", "L", ("R", "G", "B", "A")),
+ "CMYK": ("RGB", "L", ("C", "M", "Y", "K")),
+ "YCbCr": ("RGB", "L", ("Y", "Cb", "Cr")),
+
+ # Experimental modes include I;16, I;16B, RGBa, BGR;15,
+ # and BGR;24. Use these modes only if you know exactly
+ # what you're doing...
+
+}
+
+if sys.byteorder == 'little':
+ _ENDIAN = '<'
+else:
+ _ENDIAN = '>'
+
+_MODE_CONV = {
+ # official modes
+ "1": ('|b1', None),
+ "L": ('|u1', None),
+ "I": ('%si4' % _ENDIAN, None), # FIXME: is this correct?
+ "F": ('%sf4' % _ENDIAN, None), # FIXME: is this correct?
+ "P": ('|u1', None),
+ "RGB": ('|u1', 3),
+ "RGBX": ('|u1', 4),
+ "RGBA": ('|u1', 4),
+ "CMYK": ('|u1', 4),
+ "YCbCr": ('|u1', 4),
+}
+
+def _conv_type_shape(im):
+ shape = im.size[::-1]
+ typ, extra = _MODE_CONV[im.mode]
+ if extra is None:
+ return shape, typ
+ else:
+ return shape+(extra,), typ
+
+
+MODES = _MODEINFO.keys()
+MODES.sort()
+
+# raw modes that may be memory mapped. NOTE: if you change this, you
+# may have to modify the stride calculation in map.c too!
+_MAPMODES = ("L", "P", "RGBX", "RGBA", "CMYK", "I;16", "I;16B")
+
+##
+# Gets the "base" mode for given mode. This function returns "L" for
+# images that contain grayscale data, and "RGB" for images that
+# contain color data.
+#
+# @param mode Input mode.
+# @return "L" or "RGB".
+# @exception KeyError If the input mode was not a standard mode.
+
+def getmodebase(mode):
+ return ImageMode.getmode(mode).basemode
+
+##
+# Gets the storage type mode. Given a mode, this function returns a
+# single-layer mode suitable for storing individual bands.
+#
+# @param mode Input mode.
+# @return "L", "I", or "F".
+# @exception KeyError If the input mode was not a standard mode.
+
+def getmodetype(mode):
+ return ImageMode.getmode(mode).basetype
+
+##
+# Gets a list of individual band names. Given a mode, this function
+# returns a tuple containing the names of individual bands (use
+# {@link #getmodetype} to get the mode used to store each individual
+# band.
+#
+# @param mode Input mode.
+# @return A tuple containing band names. The length of the tuple
+# gives the number of bands in an image of the given mode.
+# @exception KeyError If the input mode was not a standard mode.
+
+def getmodebandnames(mode):
+ return ImageMode.getmode(mode).bands
+
+##
+# Gets the number of individual bands for this mode.
+#
+# @param mode Input mode.
+# @return The number of bands in this mode.
+# @exception KeyError If the input mode was not a standard mode.
+
+def getmodebands(mode):
+ return len(ImageMode.getmode(mode).bands)
+
+# --------------------------------------------------------------------
+# Helpers
+
+_initialized = 0
+
+##
+# Explicitly loads standard file format drivers.
+
+def preinit():
+ "Load standard file format drivers."
+
+ global _initialized
+ if _initialized >= 1:
+ return
+
+ try:
+ import BmpImagePlugin
+ except ImportError:
+ pass
+ try:
+ import GifImagePlugin
+ except ImportError:
+ pass
+ try:
+ import JpegImagePlugin
+ except ImportError:
+ pass
+ try:
+ import PpmImagePlugin
+ except ImportError:
+ pass
+ try:
+ import PngImagePlugin
+ except ImportError:
+ pass
+# try:
+# import TiffImagePlugin
+# except ImportError:
+# pass
+
+ _initialized = 1
+
+##
+# Explicitly initializes the Python Imaging Library. This function
+# loads all available file format drivers.
+
+def init():
+ "Load all file format drivers."
+
+ global _initialized
+ if _initialized >= 2:
+ return
+
+ visited = {}
+
+ directories = sys.path
+
+ try:
+ directories = directories + [os.path.dirname(__file__)]
+ except NameError:
+ pass
+
+ # only check directories (including current, if present in the path)
+ for directory in filter(isDirectory, directories):
+ fullpath = os.path.abspath(directory)
+ if visited.has_key(fullpath):
+ continue
+ for file in os.listdir(directory):
+ if file[-14:] == "ImagePlugin.py":
+ f, e = os.path.splitext(file)
+ try:
+ sys.path.insert(0, directory)
+ try:
+ __import__(f, globals(), locals(), [])
+ finally:
+ del sys.path[0]
+ except ImportError:
+ if DEBUG:
+ print "Image: failed to import",
+ print f, ":", sys.exc_value
+ visited[fullpath] = None
+
+ if OPEN or SAVE:
+ _initialized = 2
+
+
+# --------------------------------------------------------------------
+# Codec factories (used by tostring/fromstring and ImageFile.load)
+
+def _getdecoder(mode, decoder_name, args, extra=()):
+
+ # tweak arguments
+ if args is None:
+ args = ()
+ elif not isTupleType(args):
+ args = (args,)
+
+ try:
+ # get decoder
+ decoder = getattr(core, decoder_name + "_decoder")
+ # print decoder, (mode,) + args + extra
+ return apply(decoder, (mode,) + args + extra)
+ except AttributeError:
+ raise IOError("decoder %s not available" % decoder_name)
+
+def _getencoder(mode, encoder_name, args, extra=()):
+
+ # tweak arguments
+ if args is None:
+ args = ()
+ elif not isTupleType(args):
+ args = (args,)
+
+ try:
+ # get encoder
+ encoder = getattr(core, encoder_name + "_encoder")
+ # print encoder, (mode,) + args + extra
+ return apply(encoder, (mode,) + args + extra)
+ except AttributeError:
+ raise IOError("encoder %s not available" % encoder_name)
+
+
+# --------------------------------------------------------------------
+# Simple expression analyzer
+
+class _E:
+ def __init__(self, data): self.data = data
+ def __coerce__(self, other): return self, _E(other)
+ def __add__(self, other): return _E((self.data, "__add__", other.data))
+ def __mul__(self, other): return _E((self.data, "__mul__", other.data))
+
+def _getscaleoffset(expr):
+ stub = ["stub"]
+ data = expr(_E(stub)).data
+ try:
+ (a, b, c) = data # simplified syntax
+ if (a is stub and b == "__mul__" and isNumberType(c)):
+ return c, 0.0
+ if (a is stub and b == "__add__" and isNumberType(c)):
+ return 1.0, c
+ except TypeError: pass
+ try:
+ ((a, b, c), d, e) = data # full syntax
+ if (a is stub and b == "__mul__" and isNumberType(c) and
+ d == "__add__" and isNumberType(e)):
+ return c, e
+ except TypeError: pass
+ raise ValueError("illegal expression")
+
+
+# --------------------------------------------------------------------
+# Implementation wrapper
+
+##
+# This class represents an image object. To create Image objects, use
+# the appropriate factory functions. There's hardly ever any reason
+# to call the Image constructor directly.
+#
+# @see #open
+# @see #new
+# @see #fromstring
+
+class Image:
+
+ format = None
+ format_description = None
+
+ def __init__(self):
+ self.im = None
+ self.mode = ""
+ self.size = (0, 0)
+ self.palette = None
+ self.info = {}
+ self.category = NORMAL
+ self.readonly = 0
+
+ def _new(self, im):
+ new = Image()
+ new.im = im
+ new.mode = im.mode
+ new.size = im.size
+ new.palette = self.palette
+ if im.mode == "P":
+ new.palette = ImagePalette.ImagePalette()
+ try:
+ new.info = self.info.copy()
+ except AttributeError:
+ # fallback (pre-1.5.2)
+ new.info = {}
+ for k, v in self.info:
+ new.info[k] = v
+ return new
+
+ _makeself = _new # compatibility
+
+ def _copy(self):
+ self.load()
+ self.im = self.im.copy()
+ self.readonly = 0
+
+ def _dump(self, file=None, format=None):
+ import tempfile
+ if not file:
+ file = tempfile.mktemp()
+ self.load()
+ if not format or format == "PPM":
+ self.im.save_ppm(file)
+ else:
+ file = file + "." + format
+ self.save(file, format)
+ return file
+
+ def __getattr__(self, name):
+ if name == "__array_interface__":
+ # numpy array interface support
+ new = {}
+ shape, typestr = _conv_type_shape(self)
+ new['shape'] = shape
+ new['typestr'] = typestr
+ new['data'] = self.tostring()
+ return new
+ raise AttributeError(name)
+
+ ##
+ # Returns a string containing pixel data.
+ #
+ # @param encoder_name What encoder to use. The default is to
+ # use the standard "raw" encoder.
+ # @param *args Extra arguments to the encoder.
+ # @return An 8-bit string.
+
+ def tostring(self, encoder_name="raw", *args):
+ "Return image as a binary string"
+
+ # may pass tuple instead of argument list
+ if len(args) == 1 and isTupleType(args[0]):
+ args = args[0]
+
+ if encoder_name == "raw" and args == ():
+ args = self.mode
+
+ self.load()
+
+ # unpack data
+ e = _getencoder(self.mode, encoder_name, args)
+ e.setimage(self.im)
+
+ bufsize = max(65536, self.size[0] * 4) # see RawEncode.c
+
+ data = []
+ while 1:
+ l, s, d = e.encode(bufsize)
+ data.append(d)
+ if s:
+ break
+ if s < 0:
+ raise RuntimeError("encoder error %d in tostring" % s)
+
+ return string.join(data, "")
+
+ ##
+ # Returns the image converted to an X11 bitmap. This method
+ # only works for mode "1" images.
+ #
+ # @param name The name prefix to use for the bitmap variables.
+ # @return A string containing an X11 bitmap.
+ # @exception ValueError If the mode is not "1"
+
+ def tobitmap(self, name="image"):
+ "Return image as an XBM bitmap"
+
+ self.load()
+ if self.mode != "1":
+ raise ValueError("not a bitmap")
+ data = self.tostring("xbm")
+ return string.join(["#define %s_width %d\n" % (name, self.size[0]),
+ "#define %s_height %d\n"% (name, self.size[1]),
+ "static char %s_bits[] = {\n" % name, data, "};"], "")
+
+ ##
+ # Loads this image with pixel data from a string.
+ # <p>
+ # This method is similar to the {@link #fromstring} function, but
+ # loads data into this image instead of creating a new image
+ # object.
+
+ def fromstring(self, data, decoder_name="raw", *args):
+ "Load data to image from binary string"
+
+ # may pass tuple instead of argument list
+ if len(args) == 1 and isTupleType(args[0]):
+ args = args[0]
+
+ # default format
+ if decoder_name == "raw" and args == ():
+ args = self.mode
+
+ # unpack data
+ d = _getdecoder(self.mode, decoder_name, args)
+ d.setimage(self.im)
+ s = d.decode(data)
+
+ if s[0] >= 0:
+ raise ValueError("not enough image data")
+ if s[1] != 0:
+ raise ValueError("cannot decode image data")
+
+ ##
+ # Allocates storage for the image and loads the pixel data. In
+ # normal cases, you don't need to call this method, since the
+ # Image class automatically loads an opened image when it is
+ # accessed for the first time.
+ #
+ # @return An image access object.
+
+ def load(self):
+ "Explicitly load pixel data."
+ if self.im and self.palette and self.palette.dirty:
+ # realize palette
+ apply(self.im.putpalette, self.palette.getdata())
+ self.palette.dirty = 0
+ self.palette.mode = "RGB"
+ self.palette.rawmode = None
+ if self.info.has_key("transparency"):
+ self.im.putpalettealpha(self.info["transparency"], 0)
+ self.palette.mode = "RGBA"
+ if self.im:
+ return self.im.pixel_access(self.readonly)
+
+ ##
+ # Verifies the contents of a file. For data read from a file, this
+ # method attempts to determine if the file is broken, without
+ # actually decoding the image data. If this method finds any
+ # problems, it raises suitable exceptions. If you need to load
+ # the image after using this method, you must reopen the image
+ # file.
+
+ def verify(self):
+ "Verify file contents."
+ pass
+
+
+ ##
+ # Returns a converted copy of this image. For the "P" mode, this
+ # method translates pixels through the palette. If mode is
+ # omitted, a mode is chosen so that all information in the image
+ # and the palette can be represented without a palette.
+ # <p>
+ # The current version supports all possible conversions between
+ # "L", "RGB" and "CMYK."
+ # <p>
+ # When translating a colour image to black and white (mode "L"),
+ # the library uses the ITU-R 601-2 luma transform:
+ # <p>
+ # <b>L = R * 299/1000 + G * 587/1000 + B * 114/1000</b>
+ # <p>
+ # When translating a greyscale image into a bilevel image (mode
+ # "1"), all non-zero values are set to 255 (white). To use other
+ # thresholds, use the {@link #Image.point} method.
+ #
+ # @def convert(mode, matrix=None)
+ # @param mode The requested mode.
+ # @param matrix An optional conversion matrix. If given, this
+ # should be 4- or 16-tuple containing floating point values.
+ # @return An Image object.
+
+ def convert(self, mode=None, data=None, dither=None,
+ palette=WEB, colors=256):
+ "Convert to other pixel format"
+
+ if not mode:
+ # determine default mode
+ if self.mode == "P":
+ self.load()
+ if self.palette:
+ mode = self.palette.mode
+ else:
+ mode = "RGB"
+ else:
+ return self.copy()
+
+ self.load()
+
+ if data:
+ # matrix conversion
+ if mode not in ("L", "RGB"):
+ raise ValueError("illegal conversion")
+ im = self.im.convert_matrix(mode, data)
+ return self._new(im)
+
+ if mode == "P" and palette == ADAPTIVE:
+ im = self.im.quantize(colors)
+ return self._new(im)
+
+ # colourspace conversion
+ if dither is None:
+ dither = FLOYDSTEINBERG
+
+ try:
+ im = self.im.convert(mode, dither)
+ except ValueError:
+ try:
+ # normalize source image and try again
+ im = self.im.convert(getmodebase(self.mode))
+ im = im.convert(mode, dither)
+ except KeyError:
+ raise ValueError("illegal conversion")
+
+ return self._new(im)
+
+ def quantize(self, colors=256, method=0, kmeans=0, palette=None):
+
+ # methods:
+ # 0 = median cut
+ # 1 = maximum coverage
+
+ # NOTE: this functionality will be moved to the extended
+ # quantizer interface in a later version of PIL.
+
+ self.load()
+
+ if palette:
+ # use palette from reference image
+ palette.load()
+ if palette.mode != "P":
+ raise ValueError("bad mode for palette image")
+ if self.mode != "RGB" and self.mode != "L":
+ raise ValueError(
+ "only RGB or L mode images can be quantized to a palette"
+ )
+ im = self.im.convert("P", 1, palette.im)
+ return self._makeself(im)
+
+ im = self.im.quantize(colors, method, kmeans)
+ return self._new(im)
+
+ ##
+ # Copies this image. Use this method if you wish to paste things
+ # into an image, but still retain the original.
+ #
+ # @return An Image object.
+
+ def copy(self):
+ "Copy raster data"
+
+ self.load()
+ im = self.im.copy()
+ return self._new(im)
+
+ ##
+ # Returns a rectangular region from this image. The box is a
+ # 4-tuple defining the left, upper, right, and lower pixel
+ # coordinate.
+ # <p>
+ # This is a lazy operation. Changes to the source image may or
+ # may not be reflected in the cropped image. To break the
+ # connection, call the {@link #Image.load} method on the cropped
+ # copy.
+ #
+ # @param The crop rectangle, as a (left, upper, right, lower)-tuple.
+ # @return An Image object.
+
+ def crop(self, box=None):
+ "Crop region from image"
+
+ self.load()
+ if box is None:
+ return self.copy()
+
+ # lazy operation
+ return _ImageCrop(self, box)
+
+ ##
+ # Configures the image file loader so it returns a version of the
+ # image that as closely as possible matches the given mode and
+ # size. For example, you can use this method to convert a colour
+ # JPEG to greyscale while loading it, or to extract a 128x192
+ # version from a PCD file.
+ # <p>
+ # Note that this method modifies the Image object in place. If
+ # the image has already been loaded, this method has no effect.
+ #
+ # @param mode The requested mode.
+ # @param size The requested size.
+
+ def draft(self, mode, size):
+ "Configure image decoder"
+
+ pass
+
+ def _expand(self, xmargin, ymargin=None):
+ if ymargin is None:
+ ymargin = xmargin
+ self.load()
+ return self._new(self.im.expand(xmargin, ymargin, 0))
+
+ ##
+ # Filters this image using the given filter. For a list of
+ # available filters, see the <b>ImageFilter</b> module.
+ #
+ # @param filter Filter kernel.
+ # @return An Image object.
+ # @see ImageFilter
+
+ def filter(self, filter):
+ "Apply environment filter to image"
+
+ self.load()
+
+ from ImageFilter import Filter
+ if not isinstance(filter, Filter):
+ filter = filter()
+
+ if self.im.bands == 1:
+ return self._new(filter.filter(self.im))
+ # fix to handle multiband images since _imaging doesn't
+ ims = []
+ for c in range(self.im.bands):
+ ims.append(self._new(filter.filter(self.im.getband(c))))
+ return merge(self.mode, ims)
+
+ ##
+ # Returns a tuple containing the name of each band in this image.
+ # For example, <b>getbands</b> on an RGB image returns ("R", "G", "B").
+ #
+ # @return A tuple containing band names.
+
+ def getbands(self):
+ "Get band names"
+
+ return ImageMode.getmode(self.mode).bands
+
+ ##
+ # Calculates the bounding box of the non-zero regions in the
+ # image.
+ #
+ # @return The bounding box is returned as a 4-tuple defining the
+ # left, upper, right, and lower pixel coordinate. If the image
+ # is completely empty, this method returns None.
+
+ def getbbox(self):
+ "Get bounding box of actual data (non-zero pixels) in image"
+
+ self.load()
+ return self.im.getbbox()
+
+ ##
+ # Returns a list of colors used in this image.
+ #
+ # @param maxcolors Maximum number of colors. If this number is
+ # exceeded, this method returns None. The default limit is
+ # 256 colors.
+ # @return An unsorted list of (count, pixel) values.
+
+ def getcolors(self, maxcolors=256):
+ "Get colors from image, up to given limit"
+
+ self.load()
+ if self.mode in ("1", "L", "P"):
+ h = self.im.histogram()
+ out = []
+ for i in range(256):
+ if h[i]:
+ out.append((h[i], i))
+ if len(out) > maxcolors:
+ return None
+ return out
+ return self.im.getcolors(maxcolors)
+
+ ##
+ # Returns the contents of this image as a sequence object
+ # containing pixel values. The sequence object is flattened, so
+ # that values for line one follow directly after the values of
+ # line zero, and so on.
+ # <p>
+ # Note that the sequence object returned by this method is an
+ # internal PIL data type, which only supports certain sequence
+ # operations. To convert it to an ordinary sequence (e.g. for
+ # printing), use <b>list(im.getdata())</b>.
+ #
+ # @param band What band to return. The default is to return
+ # all bands. To return a single band, pass in the index
+ # value (e.g. 0 to get the "R" band from an "RGB" image).
+ # @return A sequence-like object.
+
+ def getdata(self, band = None):
+ "Get image data as sequence object."
+
+ self.load()
+ if band is not None:
+ return self.im.getband(band)
+ return self.im # could be abused
+
+ ##
+ # Gets the the minimum and maximum pixel values for each band in
+ # the image.
+ #
+ # @return For a single-band image, a 2-tuple containing the
+ # minimum and maximum pixel value. For a multi-band image,
+ # a tuple containing one 2-tuple for each band.
+
+ def getextrema(self):
+ "Get min/max value"
+
+ self.load()
+ if self.im.bands > 1:
+ extrema = []
+ for i in range(self.im.bands):
+ extrema.append(self.im.getband(i).getextrema())
+ return tuple(extrema)
+ return self.im.getextrema()
+
+ ##
+ # Returns a PyCObject that points to the internal image memory.
+ #
+ # @return A PyCObject object.
+
+ def getim(self):
+ "Get PyCObject pointer to internal image memory"
+
+ self.load()
+ return self.im.ptr
+
+
+ ##
+ # Returns the image palette as a list.
+ #
+ # @return A list of color values [r, g, b, ...], or None if the
+ # image has no palette.
+
+ def getpalette(self):
+ "Get palette contents."
+
+ self.load()
+ try:
+ return map(ord, self.im.getpalette())
+ except ValueError:
+ return None # no palette
+
+
+ ##
+ # Returns the pixel value at a given position.
+ #
+ # @param xy The coordinate, given as (x, y).
+ # @return The pixel value. If the image is a multi-layer image,
+ # this method returns a tuple.
+
+ def getpixel(self, xy):
+ "Get pixel value"
+
+ self.load()
+ return self.im.getpixel(xy)
+
+ ##
+ # Returns the horizontal and vertical projection.
+ #
+ # @return Two sequences, indicating where there are non-zero
+ # pixels along the X-axis and the Y-axis, respectively.
+
+ def getprojection(self):
+ "Get projection to x and y axes"
+
+ self.load()
+ x, y = self.im.getprojection()
+ return map(ord, x), map(ord, y)
+
+ ##
+ # Returns a histogram for the image. The histogram is returned as
+ # a list of pixel counts, one for each pixel value in the source
+ # image. If the image has more than one band, the histograms for
+ # all bands are concatenated (for example, the histogram for an
+ # "RGB" image contains 768 values).
+ # <p>
+ # A bilevel image (mode "1") is treated as a greyscale ("L") image
+ # by this method.
+ # <p>
+ # If a mask is provided, the method returns a histogram for those
+ # parts of the image where the mask image is non-zero. The mask
+ # image must have the same size as the image, and be either a
+ # bi-level image (mode "1") or a greyscale image ("L").
+ #
+ # @def histogram(mask=None)
+ # @param mask An optional mask.
+ # @return A list containing pixel counts.
+
+ def histogram(self, mask=None, extrema=None):
+ "Take histogram of image"
+
+ self.load()
+ if mask:
+ mask.load()
+ return self.im.histogram((0, 0), mask.im)
+ if self.mode in ("I", "F"):
+ if extrema is None:
+ extrema = self.getextrema()
+ return self.im.histogram(extrema)
+ return self.im.histogram()
+
+ ##
+ # (Deprecated) Returns a copy of the image where the data has been
+ # offset by the given distances. Data wraps around the edges. If
+ # yoffset is omitted, it is assumed to be equal to xoffset.
+ # <p>
+ # This method is deprecated. New code should use the <b>offset</b>
+ # function in the <b>ImageChops</b> module.
+ #
+ # @param xoffset The horizontal distance.
+ # @param yoffset The vertical distance. If omitted, both
+ # distances are set to the same value.
+ # @return An Image object.
+
+ def offset(self, xoffset, yoffset=None):
+ "(deprecated) Offset image in horizontal and/or vertical direction"
+ if warnings:
+ warnings.warn(
+ "'offset' is deprecated; use 'ImageChops.offset' instead",
+ DeprecationWarning, stacklevel=2
+ )
+ import ImageChops
+ return ImageChops.offset(self, xoffset, yoffset)
+
+ ##
+ # Pastes another image into this image. The box argument is either
+ # a 2-tuple giving the upper left corner, a 4-tuple defining the
+ # left, upper, right, and lower pixel coordinate, or None (same as
+ # (0, 0)). If a 4-tuple is given, the size of the pasted image
+ # must match the size of the region.
+ # <p>
+ # If the modes don't match, the pasted image is converted to the
+ # mode of this image (see the {@link #Image.convert} method for
+ # details).
+ # <p>
+ # Instead of an image, the source can be a integer or tuple
+ # containing pixel values. The method then fills the region
+ # with the given colour. When creating RGB images, you can
+ # also use colour strings as supported by the ImageColor module.
+ # <p>
+ # If a mask is given, this method updates only the regions
+ # indicated by the mask. You can use either "1", "L" or "RGBA"
+ # images (in the latter case, the alpha band is used as mask).
+ # Where the mask is 255, the given image is copied as is. Where
+ # the mask is 0, the current value is preserved. Intermediate
+ # values can be used for transparency effects.
+ # <p>
+ # Note that if you paste an "RGBA" image, the alpha band is
+ # ignored. You can work around this by using the same image as
+ # both source image and mask.
+ #
+ # @param im Source image or pixel value (integer or tuple).
+ # @param box An optional 4-tuple giving the region to paste into.
+ # If a 2-tuple is used instead, it's treated as the upper left
+ # corner. If omitted or None, the source is pasted into the
+ # upper left corner.
+ # <p>
+ # If an image is given as the second argument and there is no
+ # third, the box defaults to (0, 0), and the second argument
+ # is interpreted as a mask image.
+ # @param mask An optional mask image.
+ # @return An Image object.
+
+ def paste(self, im, box=None, mask=None):
+ "Paste other image into region"
+
+ if isImageType(box) and mask is None:
+ # abbreviated paste(im, mask) syntax
+ mask = box; box = None
+
+ if box is None:
+ # cover all of self
+ box = (0, 0) + self.size
+
+ if len(box) == 2:
+ # lower left corner given; get size from image or mask
+ if isImageType(im):
+ size = im.size
+ elif isImageType(mask):
+ size = mask.size
+ else:
+ # FIXME: use self.size here?
+ raise ValueError(
+ "cannot determine region size; use 4-item box"
+ )
+ box = box + (box[0]+size[0], box[1]+size[1])
+
+ if isStringType(im):
+ import ImageColor
+ im = ImageColor.getcolor(im, self.mode)
+
+ elif isImageType(im):
+ im.load()
+ if self.mode != im.mode:
+ if self.mode != "RGB" or im.mode not in ("RGBA", "RGBa"):
+ # should use an adapter for this!
+ im = im.convert(self.mode)
+ im = im.im
+
+ self.load()
+ if self.readonly:
+ self._copy()
+
+ if mask:
+ mask.load()
+ self.im.paste(im, box, mask.im)
+ else:
+ self.im.paste(im, box)
+
+ ##
+ # Maps this image through a lookup table or function.
+ #
+ # @param lut A lookup table, containing 256 values per band in the
+ # image. A function can be used instead, it should take a single
+ # argument. The function is called once for each possible pixel
+ # value, and the resulting table is applied to all bands of the
+ # image.
+ # @param mode Output mode (default is same as input). In the
+ # current version, this can only be used if the source image
+ # has mode "L" or "P", and the output has mode "1".
+ # @return An Image object.
+
+ def point(self, lut, mode=None):
+ "Map image through lookup table"
+
+ self.load()
+
+ if not isSequenceType(lut):
+ # if it isn't a list, it should be a function
+ if self.mode in ("I", "I;16", "F"):
+ # check if the function can be used with point_transform
+ scale, offset = _getscaleoffset(lut)
+ return self._new(self.im.point_transform(scale, offset))
+ # for other modes, convert the function to a table
+ lut = map(lut, range(256)) * self.im.bands
+
+ if self.mode == "F":
+ # FIXME: _imaging returns a confusing error message for this case
+ raise ValueError("point operation not supported for this mode")
+
+ return self._new(self.im.point(lut, mode))
+
+ ##
+ # Adds or replaces the alpha layer in this image. If the image
+ # does not have an alpha layer, it's converted to "LA" or "RGBA".
+ # The new layer must be either "L" or "1".
+ #
+ # @param im The new alpha layer. This can either be an "L" or "1"
+ # image having the same size as this image, or an integer or
+ # other color value.
+
+ def putalpha(self, alpha):
+ "Set alpha layer"
+
+ self.load()
+ if self.readonly:
+ self._copy()
+
+ if self.mode not in ("LA", "RGBA"):
+ # attempt to promote self to a matching alpha mode
+ try:
+ mode = getmodebase(self.mode) + "A"
+ try:
+ self.im.setmode(mode)
+ except (AttributeError, ValueError):
+ # do things the hard way
+ im = self.im.convert(mode)
+ if im.mode not in ("LA", "RGBA"):
+ raise ValueError # sanity check
+ self.im = im
+ self.mode = self.im.mode
+ except (KeyError, ValueError):
+ raise ValueError("illegal image mode")
+
+ if self.mode == "LA":
+ band = 1
+ else:
+ band = 3
+
+ if isImageType(alpha):
+ # alpha layer
+ if alpha.mode not in ("1", "L"):
+ raise ValueError("illegal image mode")
+ alpha.load()
+ if alpha.mode == "1":
+ alpha = alpha.convert("L")
+ else:
+ # constant alpha
+ try:
+ self.im.fillband(band, alpha)
+ except (AttributeError, ValueError):
+ # do things the hard way
+ alpha = new("L", self.size, alpha)
+ else:
+ return
+
+ self.im.putband(alpha.im, band)
+
+ ##
+ # Copies pixel data to this image. This method copies data from a
+ # sequence object into the image, starting at the upper left
+ # corner (0, 0), and continuing until either the image or the
+ # sequence ends. The scale and offset values are used to adjust
+ # the sequence values: <b>pixel = value*scale + offset</b>.
+ #
+ # @param data A sequence object.
+ # @param scale An optional scale value. The default is 1.0.
+ # @param offset An optional offset value. The default is 0.0.
+
+ def putdata(self, data, scale=1.0, offset=0.0):
+ "Put data from a sequence object into an image."
+
+ self.load()
+ if self.readonly:
+ self._copy()
+
+ self.im.putdata(data, scale, offset)
+
+ ##
+ # Attaches a palette to this image. The image must be a "P" or
+ # "L" image, and the palette sequence must contain 768 integer
+ # values, where each group of three values represent the red,
+ # green, and blue values for the corresponding pixel
+ # index. Instead of an integer sequence, you can use an 8-bit
+ # string.
+ #
+ # @def putpalette(data)
+ # @param data A palette sequence (either a list or a string).
+
+ def putpalette(self, data, rawmode="RGB"):
+ "Put palette data into an image."
+
+ self.load()
+ if self.mode not in ("L", "P"):
+ raise ValueError("illegal image mode")
+ if not isStringType(data):
+ data = string.join(map(chr, data), "")
+ self.mode = "P"
+ self.palette = ImagePalette.raw(rawmode, data)
+ self.palette.mode = "RGB"
+ self.load() # install new palette
+
+ ##
+ # Modifies the pixel at the given position. The colour is given as
+ # a single numerical value for single-band images, and a tuple for
+ # multi-band images.
+ # <p>
+ # Note that this method is relatively slow. For more extensive
+ # changes, use {@link #Image.paste} or the <b>ImageDraw</b> module
+ # instead.
+ #
+ # @param xy The pixel coordinate, given as (x, y).
+ # @param value The pixel value.
+ # @see #Image.paste
+ # @see #Image.putdata
+ # @see ImageDraw
+
+ def putpixel(self, xy, value):
+ "Set pixel value"
+
+ self.load()
+ if self.readonly:
+ self._copy()
+
+ return self.im.putpixel(xy, value)
+
+ ##
+ # Returns a resized copy of this image.
+ #
+ # @def resize(size, filter=NEAREST)
+ # @param size The requested size in pixels, as a 2-tuple:
+ # (width, height).
+ # @param filter An optional resampling filter. This can be
+ # one of <b>NEAREST</b> (use nearest neighbour), <b>BILINEAR</b>
+ # (linear interpolation in a 2x2 environment), <b>BICUBIC</b>
+ # (cubic spline interpolation in a 4x4 environment), or
+ # <b>ANTIALIAS</b> (a high-quality downsampling filter).
+ # If omitted, or if the image has mode "1" or "P", it is
+ # set <b>NEAREST</b>.
+ # @return An Image object.
+
+ def resize(self, size, resample=NEAREST):
+ "Resize image"
+
+ if resample not in (NEAREST, BILINEAR, BICUBIC, ANTIALIAS):
+ raise ValueError("unknown resampling filter")
+
+ self.load()
+
+ if self.mode in ("1", "P"):
+ resample = NEAREST
+
+ if resample == ANTIALIAS:
+ # requires stretch support (imToolkit & PIL 1.1.3)
+ try:
+ im = self.im.stretch(size, resample)
+ except AttributeError:
+ raise ValueError("unsupported resampling filter")
+ else:
+ im = self.im.resize(size, resample)
+
+ return self._new(im)
+
+ ##
+ # Returns a rotated copy of this image. This method returns a
+ # copy of this image, rotated the given number of degrees counter
+ # clockwise around its centre.
+ #
+ # @def rotate(angle, filter=NEAREST)
+ # @param angle In degrees counter clockwise.
+ # @param filter An optional resampling filter. This can be
+ # one of <b>NEAREST</b> (use nearest neighbour), <b>BILINEAR</b>
+ # (linear interpolation in a 2x2 environment), or <b>BICUBIC</b>
+ # (cubic spline interpolation in a 4x4 environment).
+ # If omitted, or if the image has mode "1" or "P", it is
+ # set <b>NEAREST</b>.
+ # @param expand Optional expansion flag. If true, expands the output
+ # image to make it large enough to hold the entire rotated image.
+ # If false or omitted, make the output image the same size as the
+ # input image.
+ # @return An Image object.
+
+ def rotate(self, angle, resample=NEAREST, expand=0):
+ "Rotate image. Angle given as degrees counter-clockwise."
+
+ if expand:
+ import math
+ angle = -angle * math.pi / 180
+ matrix = [
+ math.cos(angle), math.sin(angle), 0.0,
+ -math.sin(angle), math.cos(angle), 0.0
+ ]
+ def transform(x, y, (a, b, c, d, e, f)=matrix):
+ return a*x + b*y + c, d*x + e*y + f
+
+ # calculate output size
+ w, h = self.size
+ xx = []
+ yy = []
+ for x, y in ((0, 0), (w, 0), (w, h), (0, h)):
+ x, y = transform(x, y)
+ xx.append(x)
+ yy.append(y)
+ w = int(math.ceil(max(xx)) - math.floor(min(xx)))
+ h = int(math.ceil(max(yy)) - math.floor(min(yy)))
+
+ # adjust center
+ x, y = transform(w / 2.0, h / 2.0)
+ matrix[2] = self.size[0] / 2.0 - x
+ matrix[5] = self.size[1] / 2.0 - y
+
+ return self.transform((w, h), AFFINE, matrix)
+
+ if resample not in (NEAREST, BILINEAR, BICUBIC):
+ raise ValueError("unknown resampling filter")
+
+ self.load()
+
+ if self.mode in ("1", "P"):
+ resample = NEAREST
+
+ return self._new(self.im.rotate(angle, resample))
+
+ ##
+ # Saves this image under the given filename. If no format is
+ # specified, the format to use is determined from the filename
+ # extension, if possible.
+ # <p>
+ # Keyword options can be used to provide additional instructions
+ # to the writer. If a writer doesn't recognise an option, it is
+ # silently ignored. The available options are described later in
+ # this handbook.
+ # <p>
+ # You can use a file object instead of a filename. In this case,
+ # you must always specify the format. The file object must
+ # implement the <b>seek</b>, <b>tell</b>, and <b>write</b>
+ # methods, and be opened in binary mode.
+ #
+ # @def save(file, format=None, **options)
+ # @param file File name or file object.
+ # @param format Optional format override. If omitted, the
+ # format to use is determined from the filename extension.
+ # If a file object was used instead of a filename, this
+ # parameter should always be used.
+ # @param **options Extra parameters to the image writer.
+ # @return None
+ # @exception KeyError If the output format could not be determined
+ # from the file name. Use the format option to solve this.
+ # @exception IOError If the file could not be written. The file
+ # may have been created, and may contain partial data.
+
+ def save(self, fp, format=None, **params):
+ "Save image to file or stream"
+
+ if isStringType(fp):
+ filename = fp
+ else:
+ if hasattr(fp, "name") and isStringType(fp.name):
+ filename = fp.name
+ else:
+ filename = ""
+
+ # may mutate self!
+ self.load()
+
+ self.encoderinfo = params
+ self.encoderconfig = ()
+
+ preinit()
+
+ ext = string.lower(os.path.splitext(filename)[1])
+
+ if not format:
+ try:
+ format = EXTENSION[ext]
+ except KeyError:
+ init()
+ try:
+ format = EXTENSION[ext]
+ except KeyError:
+ raise KeyError(ext) # unknown extension
+
+ try:
+ save_handler = SAVE[string.upper(format)]
+ except KeyError:
+ init()
+ save_handler = SAVE[string.upper(format)] # unknown format
+
+ if isStringType(fp):
+ import __builtin__
+ fp = __builtin__.open(fp, "wb")
+ close = 1
+ else:
+ close = 0
+
+ try:
+ save_handler(self, fp, filename)
+ finally:
+ # do what we can to clean up
+ if close:
+ fp.close()
+
+ ##
+ # Seeks to the given frame in this sequence file. If you seek
+ # beyond the end of the sequence, the method raises an
+ # <b>EOFError</b> exception. When a sequence file is opened, the
+ # library automatically seeks to frame 0.
+ # <p>
+ # Note that in the current version of the library, most sequence
+ # formats only allows you to seek to the next frame.
+ #
+ # @param frame Frame number, starting at 0.
+ # @exception EOFError If the call attempts to seek beyond the end
+ # of the sequence.
+ # @see #Image.tell
+
+ def seek(self, frame):
+ "Seek to given frame in sequence file"
+
+ # overridden by file handlers
+ if frame != 0:
+ raise EOFError
+
+ ##
+ # Displays this image. This method is mainly intended for
+ # debugging purposes.
+ # <p>
+ # On Unix platforms, this method saves the image to a temporary
+ # PPM file, and calls the <b>xv</b> utility.
+ # <p>
+ # On Windows, it saves the image to a temporary BMP file, and uses
+ # the standard BMP display utility to show it (usually Paint).
+ #
+ # @def show(title=None)
+ # @param title Optional title to use for the image window,
+ # where possible.
+
+ def show(self, title=None, command=None):
+ "Display image (for debug purposes only)"
+
+ _showxv(self, title, command)
+
+ ##
+ # Split this image into individual bands. This method returns a
+ # tuple of individual image bands from an image. For example,
+ # splitting an "RGB" image creates three new images each
+ # containing a copy of one of the original bands (red, green,
+ # blue).
+ #
+ # @return A tuple containing bands.
+
+ def split(self):
+ "Split image into bands"
+
+ ims = []
+ self.load()
+ for i in range(self.im.bands):
+ ims.append(self._new(self.im.getband(i)))
+ return tuple(ims)
+
+ ##
+ # Returns the current frame number.
+ #
+ # @return Frame number, starting with 0.
+ # @see #Image.seek
+
+ def tell(self):
+ "Return current frame number"
+
+ return 0
+
+ ##
+ # Make this image into a thumbnail. This method modifies the
+ # image to contain a thumbnail version of itself, no larger than
+ # the given size. This method calculates an appropriate thumbnail
+ # size to preserve the aspect of the image, calls the {@link
+ # #Image.draft} method to configure the file reader (where
+ # applicable), and finally resizes the image.
+ # <p>
+ # Note that the bilinear and bicubic filters in the current
+ # version of PIL are not well-suited for thumbnail generation.
+ # You should use <b>ANTIALIAS</b> unless speed is much more
+ # important than quality.
+ # <p>
+ # Also note that this function modifies the Image object in place.
+ # If you need to use the full resolution image as well, apply this
+ # method to a {@link #Image.copy} of the original image.
+ #
+ # @param size Requested size.
+ # @param resample Optional resampling filter. This can be one
+ # of <b>NEAREST</b>, <b>BILINEAR</b>, <b>BICUBIC</b>, or
+ # <b>ANTIALIAS</b> (best quality). If omitted, it defaults
+ # to <b>NEAREST</b> (this will be changed to ANTIALIAS in a
+ # future version).
+ # @return None
+
+ def thumbnail(self, size, resample=NEAREST):
+ "Create thumbnail representation (modifies image in place)"
+
+ # FIXME: the default resampling filter will be changed
+ # to ANTIALIAS in future versions
+
+ # preserve aspect ratio
+ x, y = self.size
+ if x > size[0]: y = max(y * size[0] / x, 1); x = size[0]
+ if y > size[1]: x = max(x * size[1] / y, 1); y = size[1]
+ size = x, y
+
+ if size == self.size:
+ return
+
+ self.draft(None, size)
+
+ self.load()
+
+ try:
+ im = self.resize(size, resample)
+ except ValueError:
+ if resample != ANTIALIAS:
+ raise
+ im = self.resize(size, NEAREST) # fallback
+
+ self.im = im.im
+ self.mode = im.mode
+ self.size = size
+
+ self.readonly = 0
+
+ # FIXME: the different tranform methods need further explanation
+ # instead of bloating the method docs, add a separate chapter.
+
+ ##
+ # Transforms this image. This method creates a new image with the
+ # given size, and the same mode as the original, and copies data
+ # to the new image using the given transform.
+ # <p>
+ # @def transform(size, method, data, resample=NEAREST)
+ # @param size The output size.
+ # @param method The transformation method. This is one of
+ # <b>EXTENT</b> (cut out a rectangular subregion), <b>AFFINE</b>
+ # (affine transform), <b>PERSPECTIVE</b> (perspective
+ # transform), <b>QUAD</b> (map a quadrilateral to a
+ # rectangle), or <b>MESH</b> (map a number of source quadrilaterals
+ # in one operation).
+ # @param data Extra data to the transformation method.
+ # @param resample Optional resampling filter. It can be one of
+ # <b>NEAREST</b> (use nearest neighbour), <b>BILINEAR</b>
+ # (linear interpolation in a 2x2 environment), or
+ # <b>BICUBIC</b> (cubic spline interpolation in a 4x4
+ # environment). If omitted, or if the image has mode
+ # "1" or "P", it is set to <b>NEAREST</b>.
+ # @return An Image object.
+
+ def transform(self, size, method, data=None, resample=NEAREST, fill=1):
+ "Transform image"
+
+ import ImageTransform
+ if isinstance(method, ImageTransform.Transform):
+ method, data = method.getdata()
+ if data is None:
+ raise ValueError("missing method data")
+ im = new(self.mode, size, None)
+ if method == MESH:
+ # list of quads
+ for box, quad in data:
+ im.__transformer(box, self, QUAD, quad, resample, fill)
+ else:
+ im.__transformer((0, 0)+size, self, method, data, resample, fill)
+
+ return im
+
+ def __transformer(self, box, image, method, data,
+ resample=NEAREST, fill=1):
+
+ # FIXME: this should be turned into a lazy operation (?)
+
+ w = box[2]-box[0]
+ h = box[3]-box[1]
+
+ if method == AFFINE:
+ # change argument order to match implementation
+ data = (data[2], data[0], data[1],
+ data[5], data[3], data[4])
+ elif method == EXTENT:
+ # convert extent to an affine transform
+ x0, y0, x1, y1 = data
+ xs = float(x1 - x0) / w
+ ys = float(y1 - y0) / h
+ method = AFFINE
+ data = (x0 + xs/2, xs, 0, y0 + ys/2, 0, ys)
+ elif method == PERSPECTIVE:
+ # change argument order to match implementation
+ data = (data[2], data[0], data[1],
+ data[5], data[3], data[4],
+ data[6], data[7])
+ elif method == QUAD:
+ # quadrilateral warp. data specifies the four corners
+ # given as NW, SW, SE, and NE.
+ nw = data[0:2]; sw = data[2:4]; se = data[4:6]; ne = data[6:8]
+ x0, y0 = nw; As = 1.0 / w; At = 1.0 / h
+ data = (x0, (ne[0]-x0)*As, (sw[0]-x0)*At,
+ (se[0]-sw[0]-ne[0]+x0)*As*At,
+ y0, (ne[1]-y0)*As, (sw[1]-y0)*At,
+ (se[1]-sw[1]-ne[1]+y0)*As*At)
+ else:
+ raise ValueError("unknown transformation method")
+
+ if resample not in (NEAREST, BILINEAR, BICUBIC):
+ raise ValueError("unknown resampling filter")
+
+ image.load()
+
+ self.load()
+
+ if image.mode in ("1", "P"):
+ resample = NEAREST
+
+ self.im.transform2(box, image.im, method, data, resample, fill)
+
+ ##
+ # Returns a flipped or rotated copy of this image.
+ #
+ # @param method One of <b>FLIP_LEFT_RIGHT</b>, <b>FLIP_TOP_BOTTOM</b>,
+ # <b>ROTATE_90</b>, <b>ROTATE_180</b>, or <b>ROTATE_270</b>.
+
+ def transpose(self, method):
+ "Transpose image (flip or rotate in 90 degree steps)"
+
+ self.load()
+ im = self.im.transpose(method)
+ return self._new(im)
+
+# --------------------------------------------------------------------
+# Lazy operations
+
+class _ImageCrop(Image):
+
+ def __init__(self, im, box):
+
+ Image.__init__(self)
+
+ x0, y0, x1, y1 = box
+ if x1 < x0:
+ x1 = x0
+ if y1 < y0:
+ y1 = y0
+
+ self.mode = im.mode
+ self.size = x1-x0, y1-y0
+
+ self.__crop = x0, y0, x1, y1
+
+ self.im = im.im
+
+ def load(self):
+
+ # lazy evaluation!
+ if self.__crop:
+ self.im = self.im.crop(self.__crop)
+ self.__crop = None
+
+ # FIXME: future versions should optimize crop/paste
+ # sequences!
+
+# --------------------------------------------------------------------
+# Factories
+
+#
+# Debugging
+
+def _wedge():
+ "Create greyscale wedge (for debugging only)"
+
+ return Image()._new(core.wedge("L"))
+
+##
+# Creates a new image with the given mode and size.
+#
+# @param mode The mode to use for the new image.
+# @param size A 2-tuple, containing (width, height) in pixels.
+# @param color What colour to use for the image. Default is black.
+# If given, this should be a single integer or floating point value
+# for single-band modes, and a tuple for multi-band modes (one value
+# per band). When creating RGB images, you can also use colour
+# strings as supported by the ImageColor module. If the colour is
+# None, the image is not initialised.
+# @return An Image object.
+
+def new(mode, size, color=0):
+ "Create a new image"
+
+ if color is None:
+ # don't initialize
+ return Image()._new(core.new(mode, size))
+
+ if isStringType(color):
+ # css3-style specifier
+
+ import ImageColor
+ color = ImageColor.getcolor(color, mode)
+
+ return Image()._new(core.fill(mode, size, color))
+
+##
+# Creates an image memory from pixel data in a string.
+# <p>
+# In its simplest form, this function takes three arguments
+# (mode, size, and unpacked pixel data).
+# <p>
+# You can also use any pixel decoder supported by PIL. For more
+# information on available decoders, see the section <a
+# href="pil-decoder.htm"><i>Writing Your Own File Decoder</i></a>.
+# <p>
+# Note that this function decodes pixel data only, not entire images.
+# If you have an entire image in a string, wrap it in a
+# <b>StringIO</b> object, and use {@link #open} to load it.
+#
+# @param mode The image mode.
+# @param size The image size.
+# @param data An 8-bit string containing raw data for the given mode.
+# @param decoder_name What decoder to use.
+# @param *args Additional parameters for the given decoder.
+# @return An Image object.
+
+def fromstring(mode, size, data, decoder_name="raw", *args):
+ "Load image from string"
+
+ # may pass tuple instead of argument list
+ if len(args) == 1 and isTupleType(args[0]):
+ args = args[0]
+
+ if decoder_name == "raw" and args == ():
+ args = mode
+
+ im = new(mode, size)
+ im.fromstring(data, decoder_name, args)
+ return im
+
+##
+# (New in 1.1.4) Creates an image memory from pixel data in a string
+# or byte buffer.
+# <p>
+# This function is similar to {@link #fromstring}, but uses data in
+# the byte buffer, where possible. This means that changes to the
+# original buffer object are reflected in this image). Not all modes
+# can share memory; supported modes include "L", "RGBX", "RGBA", and
+# "CMYK".
+# <p>
+# Note that this function decodes pixel data only, not entire images.
+# If you have an entire image file in a string, wrap it in a
+# <b>StringIO</b> object, and use {@link #open} to load it.
+# <p>
+# In the current version, the default parameters used for the "raw"
+# decoder differs from that used for {@link fromstring}. This is a
+# bug, and will probably be fixed in a future release. The current
+# release issues a warning if you do this; to disable the warning,
+# you should provide the full set of parameters. See below for
+# details.
+#
+# @param mode The image mode.
+# @param size The image size.
+# @param data An 8-bit string or other buffer object containing raw
+# data for the given mode.
+# @param decoder_name What decoder to use.
+# @param *args Additional parameters for the given decoder. For the
+# default encoder ("raw"), it's recommended that you provide the
+# full set of parameters:
+# <b>frombuffer(mode, size, data, "raw", mode, 0, 1)</b>.
+# @return An Image object.
+# @since 1.1.4
+
+def frombuffer(mode, size, data, decoder_name="raw", *args):
+ "Load image from string or buffer"
+
+ # may pass tuple instead of argument list
+ if len(args) == 1 and isTupleType(args[0]):
+ args = args[0]
+
+ if decoder_name == "raw":
+ if args == ():
+ if warnings:
+ warnings.warn(
+ "the frombuffer defaults may change in a future release; "
+ "for portability, change the call to read:\n"
+ " frombuffer(mode, size, data, 'raw', mode, 0, 1)",
+ RuntimeWarning, stacklevel=2
+ )
+ args = mode, 0, -1 # may change to (mode, 0, 1) post-1.1.6
+ if args[0] in _MAPMODES:
+ im = new(mode, (1,1))
+ im = im._new(
+ core.map_buffer(data, size, decoder_name, None, 0, args)
+ )
+ im.readonly = 1
+ return im
+
+ return apply(fromstring, (mode, size, data, decoder_name, args))
+
+
+##
+# (New in 1.1.6) Create an image memory from an object exporting
+# the array interface (using the buffer protocol).
+#
+# If obj is not contiguous, then the tostring method is called
+# and {@link frombuffer} is used.
+#
+# @param obj Object with array interface
+# @param mode Mode to use (will be determined from type if None)
+# @return An image memory.
+
+def fromarray(obj, mode=None):
+ arr = obj.__array_interface__
+ shape = arr['shape']
+ ndim = len(shape)
+ try:
+ strides = arr['strides']
+ except KeyError:
+ strides = None
+ if mode is None:
+ typestr = arr['typestr']
+ if not (typestr[0] == '|' or typestr[0] == _ENDIAN or
+ typestr[1:] not in ['u1', 'b1', 'i4', 'f4']):
+ raise TypeError("cannot handle data-type")
+ typestr = typestr[:2]
+ if typestr == 'i4':
+ mode = 'I'
+ elif typestr == 'f4':
+ mode = 'F'
+ elif typestr == 'b1':
+ mode = '1'
+ elif ndim == 2:
+ mode = 'L'
+ elif ndim == 3:
+ mode = 'RGB'
+ elif ndim == 4:
+ mode = 'RGBA'
+ else:
+ raise TypeError("Do not understand data.")
+ ndmax = 4
+ bad_dims=0
+ if mode in ['1','L','I','P','F']:
+ ndmax = 2
+ elif mode == 'RGB':
+ ndmax = 3
+ if ndim > ndmax:
+ raise ValueError("Too many dimensions.")
+
+ size = shape[:2][::-1]
+ if strides is not None:
+ obj = obj.tostring()
+
+ return frombuffer(mode, size, obj, "raw", mode, 0, 1)
+
+##
+# Opens and identifies the given image file.
+# <p>
+# This is a lazy operation; this function identifies the file, but the
+# actual image data is not read from the file until you try to process
+# the data (or call the {@link #Image.load} method).
+#
+# @def open(file, mode="r")
+# @param file A filename (string) or a file object. The file object
+# must implement <b>read</b>, <b>seek</b>, and <b>tell</b> methods,
+# and be opened in binary mode.
+# @param mode The mode. If given, this argument must be "r".
+# @return An Image object.
+# @exception IOError If the file cannot be found, or the image cannot be
+# opened and identified.
+# @see #new
+
+def open(fp, mode="r"):
+ "Open an image file, without loading the raster data"
+
+ if mode != "r":
+ raise ValueError("bad mode")
+
+ if isStringType(fp):
+ import __builtin__
+ filename = fp
+ fp = __builtin__.open(fp, "rb")
+ else:
+ filename = ""
+
+ prefix = fp.read(16)
+
+ preinit()
+
+ for i in ID:
+ try:
+ factory, accept = OPEN[i]
+ if not accept or accept(prefix):
+ fp.seek(0)
+ return factory(fp, filename)
+ except (SyntaxError, IndexError, TypeError):
+ pass
+
+ init()
+
+ for i in ID:
+ try:
+ factory, accept = OPEN[i]
+ if not accept or accept(prefix):
+ fp.seek(0)
+ return factory(fp, filename)
+ except (SyntaxError, IndexError, TypeError):
+ pass
+
+ raise IOError("cannot identify image file")
+
+#
+# Image processing.
+
+##
+# Creates a new image by interpolating between two input images, using
+# a constant alpha.
+#
+# <pre>
+# out = image1 * (1.0 - alpha) + image2 * alpha
+# </pre>
+#
+# @param im1 The first image.
+# @param im2 The second image. Must have the same mode and size as
+# the first image.
+# @param alpha The interpolation alpha factor. If alpha is 0.0, a
+# copy of the first image is returned. If alpha is 1.0, a copy of
+# the second image is returned. There are no restrictions on the
+# alpha value. If necessary, the result is clipped to fit into
+# the allowed output range.
+# @return An Image object.
+
+def blend(im1, im2, alpha):
+ "Interpolate between images."
+
+ im1.load()
+ im2.load()
+ return im1._new(core.blend(im1.im, im2.im, alpha))
+
+##
+# Creates a new image by interpolating between two input images,
+# using the mask as alpha.
+#
+# @param image1 The first image.
+# @param image2 The second image. Must have the same mode and
+# size as the first image.
+# @param mask A mask image. This image can can have mode
+# "1", "L", or "RGBA", and must have the same size as the
+# other two images.
+
+def composite(image1, image2, mask):
+ "Create composite image by blending images using a transparency mask"
+
+ image = image2.copy()
+ image.paste(image1, None, mask)
+ return image
+
+##
+# Applies the function (which should take one argument) to each pixel
+# in the given image. If the image has more than one band, the same
+# function is applied to each band. Note that the function is
+# evaluated once for each possible pixel value, so you cannot use
+# random components or other generators.
+#
+# @def eval(image, function)
+# @param image The input image.
+# @param function A function object, taking one integer argument.
+# @return An Image object.
+
+def eval(image, *args):
+ "Evaluate image expression"
+
+ return image.point(args[0])
+
+##
+# Creates a new image from a number of single-band images.
+#
+# @param mode The mode to use for the output image.
+# @param bands A sequence containing one single-band image for
+# each band in the output image. All bands must have the
+# same size.
+# @return An Image object.
+
+def merge(mode, bands):
+ "Merge a set of single band images into a new multiband image."
+
+ if getmodebands(mode) != len(bands) or "*" in mode:
+ raise ValueError("wrong number of bands")
+ for im in bands[1:]:
+ if im.mode != getmodetype(mode):
+ raise ValueError("mode mismatch")
+ if im.size != bands[0].size:
+ raise ValueError("size mismatch")
+ im = core.new(mode, bands[0].size)
+ for i in range(getmodebands(mode)):
+ bands[i].load()
+ im.putband(bands[i].im, i)
+ return bands[0]._new(im)
+
+# --------------------------------------------------------------------
+# Plugin registry
+
+##
+# Register an image file plugin. This function should not be used
+# in application code.
+#
+# @param id An image format identifier.
+# @param factory An image file factory method.
+# @param accept An optional function that can be used to quickly
+# reject images having another format.
+
+def register_open(id, factory, accept=None):
+ id = string.upper(id)
+ ID.append(id)
+ OPEN[id] = factory, accept
+
+##
+# Registers an image MIME type. This function should not be used
+# in application code.
+#
+# @param id An image format identifier.
+# @param mimetype The image MIME type for this format.
+
+def register_mime(id, mimetype):
+ MIME[string.upper(id)] = mimetype
+
+##
+# Registers an image save function. This function should not be
+# used in application code.
+#
+# @param id An image format identifier.
+# @param driver A function to save images in this format.
+
+def register_save(id, driver):
+ SAVE[string.upper(id)] = driver
+
+##
+# Registers an image extension. This function should not be
+# used in application code.
+#
+# @param id An image format identifier.
+# @param extension An extension used for this format.
+
+def register_extension(id, extension):
+ EXTENSION[string.lower(extension)] = string.upper(id)
+
+
+# --------------------------------------------------------------------
+# Simple display support
+
+def _showxv(image, title=None, command=None):
+
+ if os.name == "nt":
+ format = "BMP"
+ elif sys.platform == "darwin":
+ format = "JPEG"
+ if not command:
+ command = "open -a /Applications/Preview.app"
+ else:
+ format = None
+ if not command:
+ command = "xv"
+ if title:
+ command = command + " -name \"%s\"" % title
+
+ if image.mode == "I;16":
+ # @PIL88 @PIL101
+ # "I;16" isn't an 'official' mode, but we still want to
+ # provide a simple way to show 16-bit images.
+ base = "L"
+ else:
+ base = getmodebase(image.mode)
+ if base != image.mode and image.mode != "1":
+ file = image.convert(base)._dump(format=format)
+ else:
+ file = image._dump(format=format)
+
+ if os.name == "nt":
+ command = "start /wait %s && del /f %s" % (file, file)
+ elif sys.platform == "darwin":
+ # on darwin open returns immediately resulting in the temp
+ # file removal while app is opening
+ command = "(%s %s; sleep 20; rm -f %s)&" % (command, file, file)
+ else:
+ command = "(%s %s; rm -f %s)&" % (command, file, file)
+
+ os.system(command)
diff --git a/Imaging/PIL/ImageChops.py b/Imaging/PIL/ImageChops.py
new file mode 100644
index 0000000..6db0710
--- /dev/null
+++ b/Imaging/PIL/ImageChops.py
@@ -0,0 +1,302 @@
+#
+# The Python Imaging Library.
+# $Id: ImageChops.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# standard channel operations
+#
+# History:
+# 1996-03-24 fl Created
+# 1996-08-13 fl Added logical operations (for "1" images)
+# 2000-10-12 fl Added offset method (from Image.py)
+#
+# Copyright (c) 1997-2000 by Secret Labs AB
+# Copyright (c) 1996-2000 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image
+
+##
+# The <b>ImageChops</b> module contains a number of arithmetical image
+# operations, called <i>channel operations</i> ("chops"). These can be
+# used for various purposes, including special effects, image
+# compositions, algorithmic painting, and more.
+# <p>
+# At this time, channel operations are only implemented for 8-bit
+# images (e.g. &quot;L&quot; and &quot;RGB&quot;).
+# <p>
+# Most channel operations take one or two image arguments and returns
+# a new image. Unless otherwise noted, the result of a channel
+# operation is always clipped to the range 0 to MAX (which is 255 for
+# all modes supported by the operations in this module).
+##
+
+##
+# Return an image with the same size as the given image, but filled
+# with the given pixel value.
+#
+# @param image Reference image.
+# @param value Pixel value.
+# @return An image object.
+
+def constant(image, value):
+ "Fill a channel with a given grey level"
+
+ return Image.new("L", image.size, value)
+
+##
+# Copy image.
+#
+# @param image Source image.
+# @return A copy of the source image.
+
+def duplicate(image):
+ "Create a copy of a channel"
+
+ return image.copy()
+
+##
+# Inverts an image
+# (MAX - image).
+#
+# @param image Source image.
+# @return An image object.
+
+def invert(image):
+ "Invert a channel"
+
+ image.load()
+ return image._new(image.im.chop_invert())
+
+##
+# Compare images, and return lighter pixel value
+# (max(image1, image2)).
+# <p>
+# Compares the two images, pixel by pixel, and returns a new image
+# containing the lighter values.
+#
+# @param image1 First image.
+# @param image1 Second image.
+# @return An image object.
+
+def lighter(image1, image2):
+ "Select the lighter pixels from each image"
+
+ image1.load()
+ image2.load()
+ return image1._new(image1.im.chop_lighter(image2.im))
+
+##
+# Compare images, and return darker pixel value
+# (min(image1, image2)).
+# <p>
+# Compares the two images, pixel by pixel, and returns a new image
+# containing the darker values.
+#
+# @param image1 First image.
+# @param image1 Second image.
+# @return An image object.
+
+def darker(image1, image2):
+ "Select the darker pixels from each image"
+
+ image1.load()
+ image2.load()
+ return image1._new(image1.im.chop_darker(image2.im))
+
+##
+# Calculate absolute difference
+# (abs(image1 - image2)).
+# <p>
+# Returns the absolute value of the difference between the two images.
+#
+# @param image1 First image.
+# @param image1 Second image.
+# @return An image object.
+
+def difference(image1, image2):
+ "Subtract one image from another"
+
+ image1.load()
+ image2.load()
+ return image1._new(image1.im.chop_difference(image2.im))
+
+##
+# Superimpose positive images
+# (image1 * image2 / MAX).
+# <p>
+# Superimposes two images on top of each other. If you multiply an
+# image with a solid black image, the result is black. If you multiply
+# with a solid white image, the image is unaffected.
+#
+# @param image1 First image.
+# @param image1 Second image.
+# @return An image object.
+
+def multiply(image1, image2):
+ "Superimpose two positive images"
+
+ image1.load()
+ image2.load()
+ return image1._new(image1.im.chop_multiply(image2.im))
+
+##
+# Superimpose negative images
+# (MAX - ((MAX - image1) * (MAX - image2) / MAX)).
+# <p>
+# Superimposes two inverted images on top of each other.
+#
+# @param image1 First image.
+# @param image1 Second image.
+# @return An image object.
+
+def screen(image1, image2):
+ "Superimpose two negative images"
+
+ image1.load()
+ image2.load()
+ return image1._new(image1.im.chop_screen(image2.im))
+
+##
+# Add images
+# ((image1 + image2) / scale + offset).
+# <p>
+# Adds two images, dividing the result by scale and adding the
+# offset. If omitted, scale defaults to 1.0, and offset to 0.0.
+#
+# @param image1 First image.
+# @param image1 Second image.
+# @return An image object.
+
+def add(image1, image2, scale=1.0, offset=0):
+ "Add two images"
+
+ image1.load()
+ image2.load()
+ return image1._new(image1.im.chop_add(image2.im, scale, offset))
+
+##
+# Subtract images
+# ((image1 - image2) / scale + offset).
+# <p>
+# Subtracts two images, dividing the result by scale and adding the
+# offset. If omitted, scale defaults to 1.0, and offset to 0.0.
+#
+# @param image1 First image.
+# @param image1 Second image.
+# @return An image object.
+
+def subtract(image1, image2, scale=1.0, offset=0):
+ "Subtract two images"
+
+ image1.load()
+ image2.load()
+ return image1._new(image1.im.chop_subtract(image2.im, scale, offset))
+
+##
+# Add images without clipping
+# ((image1 + image2) % MAX).
+# <p>
+# Adds two images, without clipping the result.
+#
+# @param image1 First image.
+# @param image1 Second image.
+# @return An image object.
+
+def add_modulo(image1, image2):
+ "Add two images without clipping"
+
+ image1.load()
+ image2.load()
+ return image1._new(image1.im.chop_add_modulo(image2.im))
+
+##
+# Subtract images without clipping
+# ((image1 - image2) % MAX).
+# <p>
+# Subtracts two images, without clipping the result.
+#
+# @param image1 First image.
+# @param image1 Second image.
+# @return An image object.
+
+def subtract_modulo(image1, image2):
+ "Subtract two images without clipping"
+
+ image1.load()
+ image2.load()
+ return image1._new(image1.im.chop_subtract_modulo(image2.im))
+
+##
+# Logical AND
+# (image1 and image2).
+
+def logical_and(image1, image2):
+ "Logical and between two images"
+
+ image1.load()
+ image2.load()
+ return image1._new(image1.im.chop_and(image2.im))
+
+##
+# Logical OR
+# (image1 or image2).
+
+def logical_or(image1, image2):
+ "Logical or between two images"
+
+ image1.load()
+ image2.load()
+ return image1._new(image1.im.chop_or(image2.im))
+
+##
+# Logical XOR
+# (image1 xor image2).
+
+def logical_xor(image1, image2):
+ "Logical xor between two images"
+
+ image1.load()
+ image2.load()
+ return image1._new(image1.im.chop_xor(image2.im))
+
+##
+# Blend images using constant transparency weight.
+# <p>
+# Same as the <b>blend</b> function in the <b>Image</b> module.
+
+def blend(image1, image2, alpha):
+ "Blend two images using a constant transparency weight"
+
+ return Image.blend(image1, image2, alpha)
+
+##
+# Create composite using transparency mask.
+# <p>
+# Same as the <b>composite</b> function in the <b>Image</b> module.
+
+def composite(image1, image2, mask):
+ "Create composite image by blending images using a transparency mask"
+
+ return Image.composite(image1, image2, mask)
+
+##
+# Offset image data.
+# <p>
+# Returns a copy of the image where data has been offset by the given
+# distances. Data wraps around the edges. If yoffset is omitted, it
+# is assumed to be equal to xoffset.
+#
+# @param image Source image.
+# @param xoffset The horizontal distance.
+# @param yoffset The vertical distance. If omitted, both
+# distances are set to the same value.
+# @return An Image object.
+
+def offset(image, xoffset, yoffset=None):
+ "Offset image in horizontal and/or vertical direction"
+ if yoffset is None:
+ yoffset = xoffset
+ image.load()
+ return image._new(image.im.offset(xoffset, yoffset))
diff --git a/Imaging/PIL/ImageColor.py b/Imaging/PIL/ImageColor.py
new file mode 100644
index 0000000..d97c0c4
--- /dev/null
+++ b/Imaging/PIL/ImageColor.py
@@ -0,0 +1,262 @@
+#
+# The Python Imaging Library
+# $Id: ImageColor.py 2813 2006-10-07 10:11:35Z fredrik $
+#
+# map CSS3-style colour description strings to RGB
+#
+# History:
+# 2002-10-24 fl Added support for CSS-style color strings
+# 2002-12-15 fl Added RGBA support
+# 2004-03-27 fl Fixed remaining int() problems for Python 1.5.2
+# 2004-07-19 fl Fixed gray/grey spelling issues
+#
+# Copyright (c) 2002-2004 by Secret Labs AB
+# Copyright (c) 2002-2004 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image
+import re, string
+
+try:
+ x = int("a", 16)
+except TypeError:
+ # python 1.5.2 doesn't support int(x,b)
+ str2int = string.atoi
+else:
+ str2int = int
+
+##
+# Convert color string to RGB tuple.
+#
+# @param color A CSS3-style colour string.
+# @return An RGB-tuple.
+# @exception ValueError If the color string could not be interpreted
+# as an RGB value.
+
+def getrgb(color):
+ # FIXME: add RGBA support
+ try:
+ rgb = colormap[color]
+ except KeyError:
+ try:
+ # fall back on case-insensitive lookup
+ rgb = colormap[string.lower(color)]
+ except KeyError:
+ rgb = None
+ # found color in cache
+ if rgb:
+ if isinstance(rgb, type(())):
+ return rgb
+ colormap[color] = rgb = getrgb(rgb)
+ return rgb
+ # check for known string formats
+ m = re.match("#\w\w\w$", color)
+ if m:
+ return (
+ str2int(color[1]*2, 16),
+ str2int(color[2]*2, 16),
+ str2int(color[3]*2, 16)
+ )
+ m = re.match("#\w\w\w\w\w\w$", color)
+ if m:
+ return (
+ str2int(color[1:3], 16),
+ str2int(color[3:5], 16),
+ str2int(color[5:7], 16)
+ )
+ m = re.match("rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$", color)
+ if m:
+ return (
+ str2int(m.group(1)),
+ str2int(m.group(2)),
+ str2int(m.group(3))
+ )
+ m = re.match("rgb\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)$", color)
+ if m:
+ return (
+ int((str2int(m.group(1)) * 255) / 100.0 + 0.5),
+ int((str2int(m.group(2)) * 255) / 100.0 + 0.5),
+ int((str2int(m.group(3)) * 255) / 100.0 + 0.5)
+ )
+ m = re.match("hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)$", color)
+ if m:
+ from colorsys import hls_to_rgb
+ rgb = hls_to_rgb(
+ float(m.group(1)) / 360.0,
+ float(m.group(3)) / 100.0,
+ float(m.group(2)) / 100.0,
+ )
+ return (
+ int(rgb[0] * 255 + 0.5),
+ int(rgb[1] * 255 + 0.5),
+ int(rgb[2] * 255 + 0.5)
+ )
+ raise ValueError("unknown color specifier: %r" % color)
+
+def getcolor(color, mode):
+ # same as getrgb, but converts the result to the given mode
+ color = getrgb(color)
+ if mode == "RGB":
+ return color
+ if mode == "RGBA":
+ r, g, b = color
+ return r, g, b, 255
+ if Image.getmodebase(mode) == "L":
+ r, g, b = color
+ return r*299/1000 + g*587/1000 + b*114/1000
+ return color
+
+colormap = {
+ # X11 colour table (from "CSS3 module: Color working draft"), with
+ # gray/grey spelling issues fixed. This is a superset of HTML 4.0
+ # colour names used in CSS 1.
+ "aliceblue": "#f0f8ff",
+ "antiquewhite": "#faebd7",
+ "aqua": "#00ffff",
+ "aquamarine": "#7fffd4",
+ "azure": "#f0ffff",
+ "beige": "#f5f5dc",
+ "bisque": "#ffe4c4",
+ "black": "#000000",
+ "blanchedalmond": "#ffebcd",
+ "blue": "#0000ff",
+ "blueviolet": "#8a2be2",
+ "brown": "#a52a2a",
+ "burlywood": "#deb887",
+ "cadetblue": "#5f9ea0",
+ "chartreuse": "#7fff00",
+ "chocolate": "#d2691e",
+ "coral": "#ff7f50",
+ "cornflowerblue": "#6495ed",
+ "cornsilk": "#fff8dc",
+ "crimson": "#dc143c",
+ "cyan": "#00ffff",
+ "darkblue": "#00008b",
+ "darkcyan": "#008b8b",
+ "darkgoldenrod": "#b8860b",
+ "darkgray": "#a9a9a9",
+ "darkgrey": "#a9a9a9",
+ "darkgreen": "#006400",
+ "darkkhaki": "#bdb76b",
+ "darkmagenta": "#8b008b",
+ "darkolivegreen": "#556b2f",
+ "darkorange": "#ff8c00",
+ "darkorchid": "#9932cc",
+ "darkred": "#8b0000",
+ "darksalmon": "#e9967a",
+ "darkseagreen": "#8fbc8f",
+ "darkslateblue": "#483d8b",
+ "darkslategray": "#2f4f4f",
+ "darkslategrey": "#2f4f4f",
+ "darkturquoise": "#00ced1",
+ "darkviolet": "#9400d3",
+ "deeppink": "#ff1493",
+ "deepskyblue": "#00bfff",
+ "dimgray": "#696969",
+ "dimgrey": "#696969",
+ "dodgerblue": "#1e90ff",
+ "firebrick": "#b22222",
+ "floralwhite": "#fffaf0",
+ "forestgreen": "#228b22",
+ "fuchsia": "#ff00ff",
+ "gainsboro": "#dcdcdc",
+ "ghostwhite": "#f8f8ff",
+ "gold": "#ffd700",
+ "goldenrod": "#daa520",
+ "gray": "#808080",
+ "grey": "#808080",
+ "green": "#008000",
+ "greenyellow": "#adff2f",
+ "honeydew": "#f0fff0",
+ "hotpink": "#ff69b4",
+ "indianred": "#cd5c5c",
+ "indigo": "#4b0082",
+ "ivory": "#fffff0",
+ "khaki": "#f0e68c",
+ "lavender": "#e6e6fa",
+ "lavenderblush": "#fff0f5",
+ "lawngreen": "#7cfc00",
+ "lemonchiffon": "#fffacd",
+ "lightblue": "#add8e6",
+ "lightcoral": "#f08080",
+ "lightcyan": "#e0ffff",
+ "lightgoldenrodyellow": "#fafad2",
+ "lightgreen": "#90ee90",
+ "lightgray": "#d3d3d3",
+ "lightgrey": "#d3d3d3",
+ "lightpink": "#ffb6c1",
+ "lightsalmon": "#ffa07a",
+ "lightseagreen": "#20b2aa",
+ "lightskyblue": "#87cefa",
+ "lightslategray": "#778899",
+ "lightslategrey": "#778899",
+ "lightsteelblue": "#b0c4de",
+ "lightyellow": "#ffffe0",
+ "lime": "#00ff00",
+ "limegreen": "#32cd32",
+ "linen": "#faf0e6",
+ "magenta": "#ff00ff",
+ "maroon": "#800000",
+ "mediumaquamarine": "#66cdaa",
+ "mediumblue": "#0000cd",
+ "mediumorchid": "#ba55d3",
+ "mediumpurple": "#9370db",
+ "mediumseagreen": "#3cb371",
+ "mediumslateblue": "#7b68ee",
+ "mediumspringgreen": "#00fa9a",
+ "mediumturquoise": "#48d1cc",
+ "mediumvioletred": "#c71585",
+ "midnightblue": "#191970",
+ "mintcream": "#f5fffa",
+ "mistyrose": "#ffe4e1",
+ "moccasin": "#ffe4b5",
+ "navajowhite": "#ffdead",
+ "navy": "#000080",
+ "oldlace": "#fdf5e6",
+ "olive": "#808000",
+ "olivedrab": "#6b8e23",
+ "orange": "#ffa500",
+ "orangered": "#ff4500",
+ "orchid": "#da70d6",
+ "palegoldenrod": "#eee8aa",
+ "palegreen": "#98fb98",
+ "paleturquoise": "#afeeee",
+ "palevioletred": "#db7093",
+ "papayawhip": "#ffefd5",
+ "peachpuff": "#ffdab9",
+ "peru": "#cd853f",
+ "pink": "#ffc0cb",
+ "plum": "#dda0dd",
+ "powderblue": "#b0e0e6",
+ "purple": "#800080",
+ "red": "#ff0000",
+ "rosybrown": "#bc8f8f",
+ "royalblue": "#4169e1",
+ "saddlebrown": "#8b4513",
+ "salmon": "#fa8072",
+ "sandybrown": "#f4a460",
+ "seagreen": "#2e8b57",
+ "seashell": "#fff5ee",
+ "sienna": "#a0522d",
+ "silver": "#c0c0c0",
+ "skyblue": "#87ceeb",
+ "slateblue": "#6a5acd",
+ "slategray": "#708090",
+ "slategrey": "#708090",
+ "snow": "#fffafa",
+ "springgreen": "#00ff7f",
+ "steelblue": "#4682b4",
+ "tan": "#d2b48c",
+ "teal": "#008080",
+ "thistle": "#d8bfd8",
+ "tomato": "#ff6347",
+ "turquoise": "#40e0d0",
+ "violet": "#ee82ee",
+ "wheat": "#f5deb3",
+ "white": "#ffffff",
+ "whitesmoke": "#f5f5f5",
+ "yellow": "#ffff00",
+ "yellowgreen": "#9acd32",
+}
diff --git a/Imaging/PIL/ImageDraw.py b/Imaging/PIL/ImageDraw.py
new file mode 100644
index 0000000..7f9107b
--- /dev/null
+++ b/Imaging/PIL/ImageDraw.py
@@ -0,0 +1,378 @@
+#
+# The Python Imaging Library
+# $Id: ImageDraw.py 2817 2006-10-07 15:34:03Z fredrik $
+#
+# drawing interface operations
+#
+# History:
+# 1996-04-13 fl Created (experimental)
+# 1996-08-07 fl Filled polygons, ellipses.
+# 1996-08-13 fl Added text support
+# 1998-06-28 fl Handle I and F images
+# 1998-12-29 fl Added arc; use arc primitive to draw ellipses
+# 1999-01-10 fl Added shape stuff (experimental)
+# 1999-02-06 fl Added bitmap support
+# 1999-02-11 fl Changed all primitives to take options
+# 1999-02-20 fl Fixed backwards compatibility
+# 2000-10-12 fl Copy on write, when necessary
+# 2001-02-18 fl Use default ink for bitmap/text also in fill mode
+# 2002-10-24 fl Added support for CSS-style color strings
+# 2002-12-10 fl Added experimental support for RGBA-on-RGB drawing
+# 2002-12-11 fl Refactored low-level drawing API (work in progress)
+# 2004-08-26 fl Made Draw() a factory function, added getdraw() support
+# 2004-09-04 fl Added width support to line primitive
+# 2004-09-10 fl Added font mode handling
+# 2006-06-19 fl Added font bearing support (getmask2)
+#
+# Copyright (c) 1997-2006 by Secret Labs AB
+# Copyright (c) 1996-2006 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image, ImageColor
+
+try:
+ import warnings
+except ImportError:
+ warnings = None
+
+##
+# A simple 2D drawing interface for PIL images.
+# <p>
+# Application code should use the <b>Draw</b> factory, instead of
+# directly.
+
+class ImageDraw:
+
+ ##
+ # Create a drawing instance.
+ #
+ # @param im The image to draw in.
+ # @param mode Optional mode to use for color values. For RGB
+ # images, this argument can be RGB or RGBA (to blend the
+ # drawing into the image). For all other modes, this argument
+ # must be the same as the image mode. If omitted, the mode
+ # defaults to the mode of the image.
+
+ def __init__(self, im, mode=None):
+ im.load()
+ if im.readonly:
+ im._copy() # make it writable
+ blend = 0
+ if mode is None:
+ mode = im.mode
+ if mode != im.mode:
+ if mode == "RGBA" and im.mode == "RGB":
+ blend = 1
+ else:
+ raise ValueError("mode mismatch")
+ if mode == "P":
+ self.palette = im.palette
+ else:
+ self.palette = None
+ self.im = im.im
+ self.draw = Image.core.draw(self.im, blend)
+ self.mode = mode
+ if mode in ("I", "F"):
+ self.ink = self.draw.draw_ink(1, mode)
+ else:
+ self.ink = self.draw.draw_ink(-1, mode)
+ if mode in ("1", "P", "I", "F"):
+ # FIXME: fix Fill2 to properly support matte for I+F images
+ self.fontmode = "1"
+ else:
+ self.fontmode = "L" # aliasing is okay for other modes
+ self.fill = 0
+ self.font = None
+
+ ##
+ # Set the default pen color.
+
+ def setink(self, ink):
+ # compatibility
+ if warnings:
+ warnings.warn(
+ "'setink' is deprecated; use keyword arguments instead",
+ DeprecationWarning, stacklevel=2
+ )
+ if Image.isStringType(ink):
+ ink = ImageColor.getcolor(ink, self.mode)
+ if self.palette and not Image.isNumberType(ink):
+ ink = self.palette.getcolor(ink)
+ self.ink = self.draw.draw_ink(ink, self.mode)
+
+ ##
+ # Set the default background color.
+
+ def setfill(self, onoff):
+ # compatibility
+ if warnings:
+ warnings.warn(
+ "'setfill' is deprecated; use keyword arguments instead",
+ DeprecationWarning, stacklevel=2
+ )
+ self.fill = onoff
+
+ ##
+ # Set the default font.
+
+ def setfont(self, font):
+ # compatibility
+ self.font = font
+
+ ##
+ # Get the current default font.
+
+ def getfont(self):
+ if not self.font:
+ # FIXME: should add a font repository
+ import ImageFont
+ self.font = ImageFont.load_default()
+ return self.font
+
+ def _getink(self, ink, fill=None):
+ if ink is None and fill is None:
+ if self.fill:
+ fill = self.ink
+ else:
+ ink = self.ink
+ else:
+ if ink is not None:
+ if Image.isStringType(ink):
+ ink = ImageColor.getcolor(ink, self.mode)
+ if self.palette and not Image.isNumberType(ink):
+ ink = self.palette.getcolor(ink)
+ ink = self.draw.draw_ink(ink, self.mode)
+ if fill is not None:
+ if Image.isStringType(fill):
+ fill = ImageColor.getcolor(fill, self.mode)
+ if self.palette and not Image.isNumberType(fill):
+ fill = self.palette.getcolor(fill)
+ fill = self.draw.draw_ink(fill, self.mode)
+ return ink, fill
+
+ ##
+ # Draw an arc.
+
+ def arc(self, xy, start, end, fill=None):
+ ink, fill = self._getink(fill)
+ if ink is not None:
+ self.draw.draw_arc(xy, start, end, ink)
+
+ ##
+ # Draw a bitmap.
+
+ def bitmap(self, xy, bitmap, fill=None):
+ bitmap.load()
+ ink, fill = self._getink(fill)
+ if ink is None:
+ ink = fill
+ if ink is not None:
+ self.draw.draw_bitmap(xy, bitmap.im, ink)
+
+ ##
+ # Draw a chord.
+
+ def chord(self, xy, start, end, fill=None, outline=None):
+ ink, fill = self._getink(outline, fill)
+ if fill is not None:
+ self.draw.draw_chord(xy, start, end, fill, 1)
+ if ink is not None:
+ self.draw.draw_chord(xy, start, end, ink, 0)
+
+ ##
+ # Draw an ellipse.
+
+ def ellipse(self, xy, fill=None, outline=None):
+ ink, fill = self._getink(outline, fill)
+ if fill is not None:
+ self.draw.draw_ellipse(xy, fill, 1)
+ if ink is not None:
+ self.draw.draw_ellipse(xy, ink, 0)
+
+ ##
+ # Draw a line, or a connected sequence of line segments.
+
+ def line(self, xy, fill=None, width=0):
+ ink, fill = self._getink(fill)
+ if ink is not None:
+ self.draw.draw_lines(xy, ink, width)
+
+ ##
+ # (Experimental) Draw a shape.
+
+ def shape(self, shape, fill=None, outline=None):
+ # experimental
+ shape.close()
+ ink, fill = self._getink(outline, fill)
+ if fill is not None:
+ self.draw.draw_outline(shape, fill, 1)
+ if ink is not None:
+ self.draw.draw_outline(shape, ink, 0)
+
+ ##
+ # Draw a pieslice.
+
+ def pieslice(self, xy, start, end, fill=None, outline=None):
+ ink, fill = self._getink(outline, fill)
+ if fill is not None:
+ self.draw.draw_pieslice(xy, start, end, fill, 1)
+ if ink is not None:
+ self.draw.draw_pieslice(xy, start, end, ink, 0)
+
+ ##
+ # Draw one or more individual pixels.
+
+ def point(self, xy, fill=None):
+ ink, fill = self._getink(fill)
+ if ink is not None:
+ self.draw.draw_points(xy, ink)
+
+ ##
+ # Draw a polygon.
+
+ def polygon(self, xy, fill=None, outline=None):
+ ink, fill = self._getink(outline, fill)
+ if fill is not None:
+ self.draw.draw_polygon(xy, fill, 1)
+ if ink is not None:
+ self.draw.draw_polygon(xy, ink, 0)
+
+ ##
+ # Draw a rectangle.
+
+ def rectangle(self, xy, fill=None, outline=None):
+ ink, fill = self._getink(outline, fill)
+ if fill is not None:
+ self.draw.draw_rectangle(xy, fill, 1)
+ if ink is not None:
+ self.draw.draw_rectangle(xy, ink, 0)
+
+ ##
+ # Draw text.
+
+ def text(self, xy, text, fill=None, font=None, anchor=None):
+ ink, fill = self._getink(fill)
+ if font is None:
+ font = self.getfont()
+ if ink is None:
+ ink = fill
+ if ink is not None:
+ try:
+ mask, offset = font.getmask2(text, self.fontmode)
+ xy = xy[0] + offset[0], xy[1] + offset[1]
+ except AttributeError:
+ try:
+ mask = font.getmask(text, self.fontmode)
+ except TypeError:
+ mask = font.getmask(text)
+ self.draw.draw_bitmap(xy, mask, ink)
+
+ ##
+ # Get the size of a given string, in pixels.
+
+ def textsize(self, text, font=None):
+ if font is None:
+ font = self.getfont()
+ return font.getsize(text)
+
+##
+# A simple 2D drawing interface for PIL images.
+#
+# @param im The image to draw in.
+# @param mode Optional mode to use for color values. For RGB
+# images, this argument can be RGB or RGBA (to blend the
+# drawing into the image). For all other modes, this argument
+# must be the same as the image mode. If omitted, the mode
+# defaults to the mode of the image.
+
+def Draw(im, mode=None):
+ try:
+ return im.getdraw(mode)
+ except AttributeError:
+ return ImageDraw(im, mode)
+
+# experimental access to the outline API
+try:
+ Outline = Image.core.outline
+except:
+ Outline = None
+
+##
+# (Experimental) A more advanced 2D drawing interface for PIL images,
+# based on the WCK interface.
+#
+# @param im The image to draw in.
+# @param hints An optional list of hints.
+# @return A (drawing context, drawing resource factory) tuple.
+
+def getdraw(im=None, hints=None):
+ # FIXME: this needs more work!
+ # FIXME: come up with a better 'hints' scheme.
+ handler = None
+ if not hints or "nicest" in hints:
+ try:
+ import _imagingagg
+ handler = _imagingagg
+ except ImportError:
+ pass
+ if handler is None:
+ import ImageDraw2
+ handler = ImageDraw2
+ if im:
+ im = handler.Draw(im)
+ return im, handler
+
+##
+# (experimental) Fills a bounded region with a given color.
+#
+# @param image Target image.
+# @param xy Seed position (a 2-item coordinate tuple).
+# @param value Fill color.
+# @param border Optional border value. If given, the region consists of
+# pixels with a color different from the border color. If not given,
+# the region consists of pixels having the same color as the seed
+# pixel.
+
+def floodfill(image, xy, value, border=None):
+ "Fill bounded region."
+ # based on an implementation by Eric S. Raymond
+ pixel = image.load()
+ x, y = xy
+ try:
+ background = pixel[x, y]
+ if background == value:
+ return # seed point already has fill color
+ pixel[x, y] = value
+ except IndexError:
+ return # seed point outside image
+ edge = [(x, y)]
+ if border is None:
+ while edge:
+ newedge = []
+ for (x, y) in edge:
+ for (s, t) in ((x+1, y), (x-1, y), (x, y+1), (x, y-1)):
+ try:
+ p = pixel[s, t]
+ except IndexError:
+ pass
+ else:
+ if p == background:
+ pixel[s, t] = value
+ newedge.append((s, t))
+ edge = newedge
+ else:
+ while edge:
+ newedge = []
+ for (x, y) in edge:
+ for (s, t) in ((x+1, y), (x-1, y), (x, y+1), (x, y-1)):
+ try:
+ p = pixel[s, t]
+ except IndexError:
+ pass
+ else:
+ if p != value and p != border:
+ pixel[s, t] = value
+ newedge.append((s, t))
+ edge = newedge
diff --git a/Imaging/PIL/ImageDraw2.py b/Imaging/PIL/ImageDraw2.py
new file mode 100644
index 0000000..65c8cbb
--- /dev/null
+++ b/Imaging/PIL/ImageDraw2.py
@@ -0,0 +1,108 @@
+#
+# The Python Imaging Library
+# $Id: ImageDraw.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# WCK-style drawing interface operations
+#
+# History:
+# 2003-12-07 fl created
+# 2005-05-15 fl updated; added to PIL as ImageDraw2
+# 2005-05-15 fl added text support
+# 2005-05-20 fl added arc/chord/pieslice support
+#
+# Copyright (c) 2003-2005 by Secret Labs AB
+# Copyright (c) 2003-2005 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image, ImageColor, ImageDraw, ImageFont, ImagePath
+
+class Pen:
+ def __init__(self, color, width=1, opacity=255):
+ self.color = ImageColor.getrgb(color)
+ self.width = width
+
+class Brush:
+ def __init__(self, color, opacity=255):
+ self.color = ImageColor.getrgb(color)
+
+class Font:
+ def __init__(self, color, file, size=12):
+ # FIXME: add support for bitmap fonts
+ self.color = ImageColor.getrgb(color)
+ self.font = ImageFont.truetype(file, size)
+
+class Draw:
+
+ def __init__(self, image, size=None, color=None):
+ if not hasattr(image, "im"):
+ image = Image.new(image, size, color)
+ self.draw = ImageDraw.Draw(image)
+ self.image = image
+ self.transform = None
+
+ def flush(self):
+ return self.image
+
+ def render(self, op, xy, pen, brush=None):
+ # handle color arguments
+ outline = fill = None; width = 1
+ if isinstance(pen, Pen):
+ outline = pen.color
+ width = pen.width
+ elif isinstance(brush, Pen):
+ outline = brush.color
+ width = brush.width
+ if isinstance(brush, Brush):
+ fill = brush.color
+ elif isinstance(pen, Brush):
+ fill = pen.color
+ # handle transformation
+ if self.transform:
+ xy = ImagePath.Path(xy)
+ xy.transform(self.transform)
+ # render the item
+ if op == "line":
+ self.draw.line(xy, fill=outline, width=width)
+ else:
+ getattr(self.draw, op)(xy, fill=fill, outline=outline)
+
+ def settransform(self, (xoffset, yoffset)):
+ self.transform = (1, 0, xoffset, 0, 1, yoffset)
+
+ def arc(self, xy, start, end, *options):
+ self.render("arc", xy, start, end, *options)
+
+ def chord(self, xy, start, end, *options):
+ self.render("chord", xy, start, end, *options)
+
+ def ellipse(self, xy, *options):
+ self.render("ellipse", xy, *options)
+
+ def pieslice(self, xy, start, end, *options):
+ self.render("pieslice", xy, start, end, *options)
+
+ def line(self, xy, *options):
+ self.render("line", xy, *options)
+
+ def rectangle(self, xy, *options):
+ self.render("rectangle", xy, *options)
+
+ def ellipse(self, xy, *options):
+ self.render("ellipse", xy, *options)
+
+ def polygon(self, xy, *options):
+ self.render("polygon", xy, *options)
+
+ def symbol(self, xy, symbol, *options):
+ raise NotImplementedError("not in this version")
+
+ def text(self, xy, text, font):
+ if self.transform:
+ xy = ImagePath.Path(xy)
+ xy.transform(self.transform)
+ self.draw.text(xy, text, font=font.font, fill=font.color)
+
+ def textsize(self, text, font):
+ return self.draw.textsize(text, font=font.font)
diff --git a/Imaging/PIL/ImageEnhance.py b/Imaging/PIL/ImageEnhance.py
new file mode 100644
index 0000000..cddd084
--- /dev/null
+++ b/Imaging/PIL/ImageEnhance.py
@@ -0,0 +1,89 @@
+#
+# The Python Imaging Library.
+# $Id: ImageEnhance.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# image enhancement classes
+#
+# For a background, see "Image Processing By Interpolation and
+# Extrapolation", Paul Haeberli and Douglas Voorhies. Available
+# at http://www.sgi.com/grafica/interp/index.html
+#
+# History:
+# 96-03-23 fl Created
+#
+# Copyright (c) Secret Labs AB 1997.
+# Copyright (c) Fredrik Lundh 1996.
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image, ImageFilter
+
+class _Enhance:
+
+ ##
+ # Returns an enhanced image. The enhancement factor is a floating
+ # point value controlling the enhancement. Factor 1.0 always
+ # returns a copy of the original image, lower factors mean less
+ # colour (brightness, contrast, etc), and higher values more.
+ # There are no restrictions on this value.
+ #
+ # @param factor Enhancement factor.
+ # @return An enhanced image.
+
+ def enhance(self, factor):
+ return Image.blend(self.degenerate, self.image, factor)
+
+##
+# Color enhancement object.
+# <p>
+# This class can be used to adjust the colour balance of an image, in
+# a manner similar to the controls on a colour TV set. An enhancement
+# factor of 0.0 gives a black and white image, a factor of 1.0 gives
+# the original image.
+
+class Color(_Enhance):
+ "Adjust image colour balance"
+ def __init__(self, image):
+ self.image = image
+ self.degenerate = image.convert("L").convert(image.mode)
+
+##
+# Contrast enhancement object.
+# <p>
+# This class can be used to control the contrast of an image, similar
+# to the contrast control on a TV set. An enhancement factor of 0.0
+# gives an solid grey image, factor 1.0 gives the original image.
+
+class Contrast(_Enhance):
+ "Adjust image contrast"
+ def __init__(self, image):
+ self.image = image
+ mean = reduce(lambda a,b: a+b, image.convert("L").histogram())/256.0
+ self.degenerate = Image.new("L", image.size, mean).convert(image.mode)
+
+##
+# Brightness enhancement object.
+# <p>
+# This class can be used to control the brighntess of an image. An
+# enhancement factor of 0.0 gives a black image, factor 1.0 gives the
+# original image.
+
+class Brightness(_Enhance):
+ "Adjust image brightness"
+ def __init__(self, image):
+ self.image = image
+ self.degenerate = Image.new(image.mode, image.size, 0)
+
+##
+# Sharpness enhancement object.
+# <p>
+# This class can be used to adjust the sharpness of an image. The
+# enhancement factor 0.0 gives a blurred image, 1.0 gives the original
+# image, and a factor of 2.0 gives a sharpened image.
+
+class Sharpness(_Enhance):
+ "Adjust image sharpness"
+ def __init__(self, image):
+ self.image = image
+ self.degenerate = image.filter(ImageFilter.SMOOTH)
diff --git a/Imaging/PIL/ImageFile.py b/Imaging/PIL/ImageFile.py
new file mode 100644
index 0000000..d51aff3
--- /dev/null
+++ b/Imaging/PIL/ImageFile.py
@@ -0,0 +1,520 @@
+#
+# The Python Imaging Library.
+# $Id: ImageFile.py 2930 2006-12-02 13:50:40Z fredrik $
+#
+# base class for image file handlers
+#
+# history:
+# 1995-09-09 fl Created
+# 1996-03-11 fl Fixed load mechanism.
+# 1996-04-15 fl Added pcx/xbm decoders.
+# 1996-04-30 fl Added encoders.
+# 1996-12-14 fl Added load helpers
+# 1997-01-11 fl Use encode_to_file where possible
+# 1997-08-27 fl Flush output in _save
+# 1998-03-05 fl Use memory mapping for some modes
+# 1999-02-04 fl Use memory mapping also for "I;16" and "I;16B"
+# 1999-05-31 fl Added image parser
+# 2000-10-12 fl Set readonly flag on memory-mapped images
+# 2002-03-20 fl Use better messages for common decoder errors
+# 2003-04-21 fl Fall back on mmap/map_buffer if map is not available
+# 2003-10-30 fl Added StubImageFile class
+# 2004-02-25 fl Made incremental parser more robust
+#
+# Copyright (c) 1997-2004 by Secret Labs AB
+# Copyright (c) 1995-2004 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image
+import traceback, sys, string, os
+
+MAXBLOCK = 65536
+
+SAFEBLOCK = 1024*1024
+
+ERRORS = {
+ -1: "image buffer overrun error",
+ -2: "decoding error",
+ -3: "unknown error",
+ -8: "bad configuration",
+ -9: "out of memory error"
+}
+
+#
+# --------------------------------------------------------------------
+# Helpers
+
+def _tilesort(t1, t2):
+ # sort on offset
+ return cmp(t1[2], t2[2])
+
+#
+# --------------------------------------------------------------------
+# ImageFile base class
+
+##
+# Base class for image file handlers.
+
+class ImageFile(Image.Image):
+ "Base class for image file format handlers."
+
+ def __init__(self, fp=None, filename=None):
+ Image.Image.__init__(self)
+
+ self.tile = None
+ self.readonly = 1 # until we know better
+
+ self.decoderconfig = ()
+ self.decodermaxblock = MAXBLOCK
+
+ if Image.isStringType(fp):
+ # filename
+ self.fp = open(fp, "rb")
+ self.filename = fp
+ else:
+ # stream
+ self.fp = fp
+ self.filename = filename
+
+ try:
+ self._open()
+ except IndexError, v: # end of data
+ if Image.DEBUG > 1:
+ traceback.print_exc()
+ raise SyntaxError, v
+ except TypeError, v: # end of data (ord)
+ if Image.DEBUG > 1:
+ traceback.print_exc()
+ raise SyntaxError, v
+ except KeyError, v: # unsupported mode
+ if Image.DEBUG > 1:
+ traceback.print_exc()
+ raise SyntaxError, v
+ except EOFError, v: # got header but not the first frame
+ if Image.DEBUG > 1:
+ traceback.print_exc()
+ raise SyntaxError, v
+
+ if not self.mode or self.size[0] <= 0:
+ raise SyntaxError, "not identified by this driver"
+
+ def draft(self, mode, size):
+ "Set draft mode"
+
+ pass
+
+ def verify(self):
+ "Check file integrity"
+
+ # raise exception if something's wrong. must be called
+ # directly after open, and closes file when finished.
+ self.fp = None
+
+ def load(self):
+ "Load image data based on tile list"
+
+ pixel = Image.Image.load(self)
+
+ if self.tile is None:
+ raise IOError("cannot load this image")
+ if not self.tile:
+ return pixel
+
+ self.map = None
+
+ readonly = 0
+
+ if self.filename and len(self.tile) == 1:
+ # try memory mapping
+ d, e, o, a = self.tile[0]
+ if d == "raw" and a[0] == self.mode and a[0] in Image._MAPMODES:
+ try:
+ if hasattr(Image.core, "map"):
+ # use built-in mapper
+ self.map = Image.core.map(self.filename)
+ self.map.seek(o)
+ self.im = self.map.readimage(
+ self.mode, self.size, a[1], a[2]
+ )
+ else:
+ # use mmap, if possible
+ import mmap
+ file = open(self.filename, "r+")
+ size = os.path.getsize(self.filename)
+ # FIXME: on Unix, use PROT_READ etc
+ self.map = mmap.mmap(file.fileno(), size)
+ self.im = Image.core.map_buffer(
+ self.map, self.size, d, e, o, a
+ )
+ readonly = 1
+ except (AttributeError, EnvironmentError, ImportError):
+ self.map = None
+
+ self.load_prepare()
+
+ # look for read/seek overrides
+ try:
+ read = self.load_read
+ except AttributeError:
+ read = self.fp.read
+
+ try:
+ seek = self.load_seek
+ except AttributeError:
+ seek = self.fp.seek
+
+ if not self.map:
+
+ # sort tiles in file order
+ self.tile.sort(_tilesort)
+
+ try:
+ # FIXME: This is a hack to handle TIFF's JpegTables tag.
+ prefix = self.tile_prefix
+ except AttributeError:
+ prefix = ""
+
+ for d, e, o, a in self.tile:
+ d = Image._getdecoder(self.mode, d, a, self.decoderconfig)
+ seek(o)
+ try:
+ d.setimage(self.im, e)
+ except ValueError:
+ continue
+ b = prefix
+ t = len(b)
+ while 1:
+ s = read(self.decodermaxblock)
+ if not s:
+ self.tile = []
+ raise IOError("image file is truncated (%d bytes not processed)" % len(b))
+ b = b + s
+ n, e = d.decode(b)
+ if n < 0:
+ break
+ b = b[n:]
+ t = t + n
+
+ self.tile = []
+ self.readonly = readonly
+
+ self.fp = None # might be shared
+
+ if not self.map and e < 0:
+ error = ERRORS.get(e, "decoder error %d" % e)
+ raise IOError(error + " when reading image file")
+
+ # post processing
+ if hasattr(self, "tile_post_rotate"):
+ # FIXME: This is a hack to handle rotated PCD's
+ self.im = self.im.rotate(self.tile_post_rotate)
+ self.size = self.im.size
+
+ self.load_end()
+
+ return Image.Image.load(self)
+
+ def load_prepare(self):
+ # create image memory if necessary
+ if not self.im or\
+ self.im.mode != self.mode or self.im.size != self.size:
+ self.im = Image.core.new(self.mode, self.size)
+ # create palette (optional)
+ if self.mode == "P":
+ Image.Image.load(self)
+
+ def load_end(self):
+ # may be overridden
+ pass
+
+ # may be defined for contained formats
+ # def load_seek(self, pos):
+ # pass
+
+ # may be defined for blocked formats (e.g. PNG)
+ # def load_read(self, bytes):
+ # pass
+
+##
+# Base class for stub image loaders.
+# <p>
+# A stub loader is an image loader that can identify files of a
+# certain format, but relies on external code to load the file.
+
+class StubImageFile(ImageFile):
+ "Base class for stub image loaders."
+
+ def _open(self):
+ raise NotImplementedError(
+ "StubImageFile subclass must implement _open"
+ )
+
+ def load(self):
+ loader = self._load()
+ if loader is None:
+ raise IOError("cannot find loader for this %s file" % self.format)
+ image = loader.load(self)
+ assert image is not None
+ # become the other object (!)
+ self.__class__ = image.__class__
+ self.__dict__ = image.__dict__
+
+ ##
+ # (Hook) Find actual image loader.
+
+ def _load(self):
+ raise NotImplementedError(
+ "StubImageFile subclass must implement _load"
+ )
+
+##
+# (Internal) Support class for the <b>Parser</b> file.
+
+class _ParserFile:
+ # parser support class.
+
+ def __init__(self, data):
+ self.data = data
+ self.offset = 0
+
+ def close(self):
+ self.data = self.offset = None
+
+ def tell(self):
+ return self.offset
+
+ def seek(self, offset, whence=0):
+ if whence == 0:
+ self.offset = offset
+ elif whence == 1:
+ self.offset = self.offset + offset
+ else:
+ # force error in Image.open
+ raise IOError("illegal argument to seek")
+
+ def read(self, bytes=0):
+ pos = self.offset
+ if bytes:
+ data = self.data[pos:pos+bytes]
+ else:
+ data = self.data[pos:]
+ self.offset = pos + len(data)
+ return data
+
+ def readline(self):
+ # FIXME: this is slow!
+ s = ""
+ while 1:
+ c = self.read(1)
+ if not c:
+ break
+ s = s + c
+ if c == "\n":
+ break
+ return s
+
+##
+# Incremental image parser. This class implements the standard
+# feed/close consumer interface.
+
+class Parser:
+
+ incremental = None
+ image = None
+ data = None
+ decoder = None
+ finished = 0
+
+ ##
+ # (Consumer) Reset the parser. Note that you can only call this
+ # method immediately after you've created a parser; parser
+ # instances cannot be reused.
+
+ def reset(self):
+ assert self.data is None, "cannot reuse parsers"
+
+ ##
+ # (Consumer) Feed data to the parser.
+ #
+ # @param data A string buffer.
+ # @exception IOError If the parser failed to parse the image file.
+
+ def feed(self, data):
+ # collect data
+
+ if self.finished:
+ return
+
+ if self.data is None:
+ self.data = data
+ else:
+ self.data = self.data + data
+
+ # parse what we have
+ if self.decoder:
+
+ if self.offset > 0:
+ # skip header
+ skip = min(len(self.data), self.offset)
+ self.data = self.data[skip:]
+ self.offset = self.offset - skip
+ if self.offset > 0 or not self.data:
+ return
+
+ n, e = self.decoder.decode(self.data)
+
+ if n < 0:
+ # end of stream
+ self.data = None
+ self.finished = 1
+ if e < 0:
+ # decoding error
+ self.image = None
+ error = ERRORS.get(e, "decoder error %d" % e)
+ raise IOError(error + " when reading image file")
+ else:
+ # end of image
+ return
+ self.data = self.data[n:]
+
+ elif self.image:
+
+ # if we end up here with no decoder, this file cannot
+ # be incrementally parsed. wait until we've gotten all
+ # available data
+ pass
+
+ else:
+
+ # attempt to open this file
+ try:
+ try:
+ fp = _ParserFile(self.data)
+ im = Image.open(fp)
+ finally:
+ fp.close() # explicitly close the virtual file
+ except IOError:
+ pass # not enough data
+ else:
+ flag = hasattr(im, "load_seek") or hasattr(im, "load_read")
+ if flag or len(im.tile) != 1:
+ # custom load code, or multiple tiles
+ self.decode = None
+ else:
+ # initialize decoder
+ im.load_prepare()
+ d, e, o, a = im.tile[0]
+ im.tile = []
+ self.decoder = Image._getdecoder(
+ im.mode, d, a, im.decoderconfig
+ )
+ self.decoder.setimage(im.im, e)
+
+ # calculate decoder offset
+ self.offset = o
+ if self.offset <= len(self.data):
+ self.data = self.data[self.offset:]
+ self.offset = 0
+
+ self.image = im
+
+ ##
+ # (Consumer) Close the stream.
+ #
+ # @return An image object.
+ # @exception IOError If the parser failed to parse the image file.
+
+ def close(self):
+ # finish decoding
+ if self.decoder:
+ # get rid of what's left in the buffers
+ self.feed("")
+ self.data = self.decoder = None
+ if not self.finished:
+ raise IOError("image was incomplete")
+ if not self.image:
+ raise IOError("cannot parse this image")
+ if self.data:
+ # incremental parsing not possible; reopen the file
+ # not that we have all data
+ try:
+ fp = _ParserFile(self.data)
+ self.image = Image.open(fp)
+ finally:
+ fp.close() # explicitly close the virtual file
+ return self.image
+
+# --------------------------------------------------------------------
+
+##
+# (Helper) Save image body to file.
+#
+# @param im Image object.
+# @param fp File object.
+# @param tile Tile list.
+
+def _save(im, fp, tile):
+ "Helper to save image based on tile list"
+
+ im.load()
+ if not hasattr(im, "encoderconfig"):
+ im.encoderconfig = ()
+ tile.sort(_tilesort)
+ # FIXME: make MAXBLOCK a configuration parameter
+ bufsize = max(MAXBLOCK, im.size[0] * 4) # see RawEncode.c
+ try:
+ fh = fp.fileno()
+ fp.flush()
+ except AttributeError:
+ # compress to Python file-compatible object
+ for e, b, o, a in tile:
+ e = Image._getencoder(im.mode, e, a, im.encoderconfig)
+ if o > 0:
+ fp.seek(o, 0)
+ e.setimage(im.im, b)
+ while 1:
+ l, s, d = e.encode(bufsize)
+ fp.write(d)
+ if s:
+ break
+ if s < 0:
+ raise IOError("encoder error %d when writing image file" % s)
+ else:
+ # slight speedup: compress to real file object
+ for e, b, o, a in tile:
+ e = Image._getencoder(im.mode, e, a, im.encoderconfig)
+ if o > 0:
+ fp.seek(o, 0)
+ e.setimage(im.im, b)
+ s = e.encode_to_file(fh, bufsize)
+ if s < 0:
+ raise IOError("encoder error %d when writing image file" % s)
+ try:
+ fp.flush()
+ except: pass
+
+
+##
+# Reads large blocks in a safe way. Unlike fp.read(n), this function
+# doesn't trust the user. If the requested size is larger than
+# SAFEBLOCK, the file is read block by block.
+#
+# @param fp File handle. Must implement a <b>read</b> method.
+# @param size Number of bytes to read.
+# @return A string containing up to <i>size</i> bytes of data.
+
+def _safe_read(fp, size):
+ if size <= 0:
+ return ""
+ if size <= SAFEBLOCK:
+ return fp.read(size)
+ data = []
+ while size > 0:
+ block = fp.read(min(size, SAFEBLOCK))
+ if not block:
+ break
+ data.append(block)
+ size = size - len(block)
+ return string.join(data, "")
diff --git a/Imaging/PIL/ImageFileIO.py b/Imaging/PIL/ImageFileIO.py
new file mode 100644
index 0000000..7c6a5c1
--- /dev/null
+++ b/Imaging/PIL/ImageFileIO.py
@@ -0,0 +1,47 @@
+#
+# The Python Imaging Library.
+# $Id: ImageFileIO.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# kludge to get basic ImageFileIO functionality
+#
+# History:
+# 1998-08-06 fl Recreated
+#
+# Copyright (c) Secret Labs AB 1998-2002.
+#
+# See the README file for information on usage and redistribution.
+#
+
+from StringIO import StringIO
+
+##
+# The <b>ImageFileIO</b> module can be used to read an image from a
+# socket, or any other stream device.
+# <p>
+# This module is deprecated. New code should use the <b>Parser</b>
+# class in the <a href="imagefile">ImageFile</a> module instead.
+#
+# @see ImageFile#Parser
+
+class ImageFileIO(StringIO):
+
+ ##
+ # Adds buffering to a stream file object, in order to
+ # provide <b>seek</b> and <b>tell</b> methods required
+ # by the <b>Image.open</b> method. The stream object must
+ # implement <b>read</b> and <b>close</b> methods.
+ #
+ # @param fp Stream file handle.
+ # @see Image#open
+
+ def __init__(self, fp):
+ data = fp.read()
+ StringIO.__init__(self, data)
+
+if __name__ == "__main__":
+
+ import Image
+ fp = open("/images/clenna.im", "rb")
+ im = Image.open(ImageFileIO(fp))
+ im.load() # make sure we can read the raster data
+ print im.mode, im.size
diff --git a/Imaging/PIL/ImageFilter.py b/Imaging/PIL/ImageFilter.py
new file mode 100644
index 0000000..5857686
--- /dev/null
+++ b/Imaging/PIL/ImageFilter.py
@@ -0,0 +1,263 @@
+#
+# The Python Imaging Library.
+# $Id: ImageFilter.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# standard filters
+#
+# History:
+# 1995-11-27 fl Created
+# 2002-06-08 fl Added rank and mode filters
+# 2003-09-15 fl Fixed rank calculation in rank filter; added expand call
+#
+# Copyright (c) 1997-2003 by Secret Labs AB.
+# Copyright (c) 1995-2002 by Fredrik Lundh.
+#
+# See the README file for information on usage and redistribution.
+#
+
+class Filter:
+ pass
+
+##
+# Convolution filter kernel.
+
+class Kernel(Filter):
+
+ ##
+ # Create a convolution kernel. The current version only
+ # supports 3x3 and 5x5 integer and floating point kernels.
+ # <p>
+ # In the current version, kernels can only be applied to
+ # "L" and "RGB" images.
+ #
+ # @def __init__(size, kernel, **options)
+ # @param size Kernel size, given as (width, height). In
+ # the current version, this must be (3,3) or (5,5).
+ # @param kernel A sequence containing kernel weights.
+ # @param **options Optional keyword arguments.
+ # @keyparam scale Scale factor. If given, the result for each
+ # pixel is divided by this value. The default is the sum
+ # of the kernel weights.
+ # @keyparam offset Offset. If given, this value is added to the
+ # result, after it has been divided by the scale factor.
+
+ def __init__(self, size, kernel, scale=None, offset=0):
+ if scale is None:
+ # default scale is sum of kernel
+ scale = reduce(lambda a,b: a+b, kernel)
+ if size[0] * size[1] != len(kernel):
+ raise ValueError("not enough coefficients in kernel")
+ self.filterargs = size, scale, offset, kernel
+
+ def filter(self, image):
+ if image.mode == "P":
+ raise ValueError("cannot filter palette images")
+ return apply(image.filter, self.filterargs)
+
+class BuiltinFilter(Kernel):
+ def __init__(self):
+ pass
+
+##
+# Rank filter.
+
+class RankFilter(Filter):
+ name = "Rank"
+
+ ##
+ # Create a rank filter. The rank filter sorts all pixels in
+ # a window of the given size, and returns the rank'th value.
+ #
+ # @param size The kernel size, in pixels.
+ # @param rank What pixel value to pick. Use 0 for a min filter,
+ # size*size/2 for a median filter, size*size-1 for a max filter,
+ # etc.
+
+ def __init__(self, size, rank):
+ self.size = size
+ self.rank = rank
+
+ def filter(self, image):
+ image = image.expand(self.size/2, self.size/2)
+ return image.rankfilter(self.size, self.rank)
+
+##
+# Median filter. Picks the median pixel value in a window with the
+# given size.
+
+class MedianFilter(RankFilter):
+ name = "Median"
+
+ ##
+ # Create a median filter.
+ #
+ # @param size The kernel size, in pixels.
+
+ def __init__(self, size=3):
+ self.size = size
+ self.rank = size*size/2
+
+##
+# Min filter. Picks the lowest pixel value in a window with the given
+# size.
+
+class MinFilter(RankFilter):
+ name = "Min"
+
+ ##
+ # Create a min filter.
+ #
+ # @param size The kernel size, in pixels.
+
+ def __init__(self, size=3):
+ self.size = size
+ self.rank = 0
+
+##
+# Max filter. Picks the largest pixel value in a window with the
+# given size.
+
+class MaxFilter(RankFilter):
+ name = "Max"
+
+ ##
+ # Create a max filter.
+ #
+ # @param size The kernel size, in pixels.
+
+ def __init__(self, size=3):
+ self.size = size
+ self.rank = size*size-1
+
+##
+# Mode filter. Picks the most frequent pixel value in a box with the
+# given size. Pixel values that occur only once or twice are ignored;
+# if no pixel value occurs more than twice, the original pixel value
+# is preserved.
+
+class ModeFilter(Filter):
+ name = "Mode"
+
+ ##
+ # Create a mode filter.
+ #
+ # @param size The kernel size, in pixels.
+
+ def __init__(self, size=3):
+ self.size = size
+ def filter(self, image):
+ return image.modefilter(self.size)
+
+##
+# Blur filter.
+
+class BLUR(BuiltinFilter):
+ name = "Blur"
+ filterargs = (5, 5), 16, 0, (
+ 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 1,
+ 1, 0, 0, 0, 1,
+ 1, 0, 0, 0, 1,
+ 1, 1, 1, 1, 1
+ )
+
+##
+# Contour filter.
+
+class CONTOUR(BuiltinFilter):
+ name = "Contour"
+ filterargs = (3, 3), 1, 255, (
+ -1, -1, -1,
+ -1, 8, -1,
+ -1, -1, -1
+ )
+
+##
+# Detail filter.
+
+class DETAIL(BuiltinFilter):
+ name = "Detail"
+ filterargs = (3, 3), 6, 0, (
+ 0, -1, 0,
+ -1, 10, -1,
+ 0, -1, 0
+ )
+
+##
+# Edge enhancement filter.
+
+class EDGE_ENHANCE(BuiltinFilter):
+ name = "Edge-enhance"
+ filterargs = (3, 3), 2, 0, (
+ -1, -1, -1,
+ -1, 10, -1,
+ -1, -1, -1
+ )
+
+##
+# Stronger edge enhancement filter.
+
+class EDGE_ENHANCE_MORE(BuiltinFilter):
+ name = "Edge-enhance More"
+ filterargs = (3, 3), 1, 0, (
+ -1, -1, -1,
+ -1, 9, -1,
+ -1, -1, -1
+ )
+
+##
+# Embossing filter.
+
+class EMBOSS(BuiltinFilter):
+ name = "Emboss"
+ filterargs = (3, 3), 1, 128, (
+ -1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 0
+ )
+
+##
+# Edge-finding filter.
+
+class FIND_EDGES(BuiltinFilter):
+ name = "Find Edges"
+ filterargs = (3, 3), 1, 0, (
+ -1, -1, -1,
+ -1, 8, -1,
+ -1, -1, -1
+ )
+
+##
+# Smoothing filter.
+
+class SMOOTH(BuiltinFilter):
+ name = "Smooth"
+ filterargs = (3, 3), 13, 0, (
+ 1, 1, 1,
+ 1, 5, 1,
+ 1, 1, 1
+ )
+
+##
+# Stronger smoothing filter.
+
+class SMOOTH_MORE(BuiltinFilter):
+ name = "Smooth More"
+ filterargs = (5, 5), 100, 0, (
+ 1, 1, 1, 1, 1,
+ 1, 5, 5, 5, 1,
+ 1, 5, 44, 5, 1,
+ 1, 5, 5, 5, 1,
+ 1, 1, 1, 1, 1
+ )
+
+##
+# Sharpening filter.
+
+class SHARPEN(BuiltinFilter):
+ name = "Sharpen"
+ filterargs = (3, 3), 16, 0, (
+ -2, -2, -2,
+ -2, 32, -2,
+ -2, -2, -2
+ )
diff --git a/Imaging/PIL/ImageFont.py b/Imaging/PIL/ImageFont.py
new file mode 100644
index 0000000..b987a33
--- /dev/null
+++ b/Imaging/PIL/ImageFont.py
@@ -0,0 +1,377 @@
+#
+# The Python Imaging Library.
+# $Id: ImageFont.py 2813 2006-10-07 10:11:35Z fredrik $
+#
+# PIL raster font management
+#
+# History:
+# 1996-08-07 fl created (experimental)
+# 1997-08-25 fl minor adjustments to handle fonts from pilfont 0.3
+# 1999-02-06 fl rewrote most font management stuff in C
+# 1999-03-17 fl take pth files into account in load_path (from Richard Jones)
+# 2001-02-17 fl added freetype support
+# 2001-05-09 fl added TransposedFont wrapper class
+# 2002-03-04 fl make sure we have a "L" or "1" font
+# 2002-12-04 fl skip non-directory entries in the system path
+# 2003-04-29 fl add embedded default font
+# 2003-09-27 fl added support for truetype charmap encodings
+#
+# Todo:
+# Adapt to PILFONT2 format (16-bit fonts, compressed, single file)
+#
+# Copyright (c) 1997-2003 by Secret Labs AB
+# Copyright (c) 1996-2003 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image
+import os, string, sys
+
+# FIXME: add support for pilfont2 format (see FontFile.py)
+
+# --------------------------------------------------------------------
+# Font metrics format:
+# "PILfont" LF
+# fontdescriptor LF
+# (optional) key=value... LF
+# "DATA" LF
+# binary data: 256*10*2 bytes (dx, dy, dstbox, srcbox)
+#
+# To place a character, cut out srcbox and paste at dstbox,
+# relative to the character position. Then move the character
+# position according to dx, dy.
+# --------------------------------------------------------------------
+
+##
+# The <b>ImageFont</b> module defines a class with the same name.
+# Instances of this class store bitmap fonts, and are used with the
+# <b>text</b> method of the <b>ImageDraw</b> class.
+# <p>
+# PIL uses it's own font file format to store bitmap fonts. You can
+# use the <b>pilfont</b> utility to convert BDF and PCF font
+# descriptors (X window font formats) to this format.
+# <p>
+# Starting with version 1.1.4, PIL can be configured to support
+# TrueType and OpenType fonts. For earlier version, TrueType
+# support is only available as part of the imToolkit package
+#
+# @see ImageDraw#ImageDraw.text
+# @see pilfont
+
+class ImageFont:
+ "PIL font wrapper"
+
+ def _load_pilfont(self, filename):
+
+ file = open(filename, "rb")
+
+ for ext in (".png", ".gif", ".pbm"):
+ try:
+ fullname = os.path.splitext(filename)[0] + ext
+ image = Image.open(fullname)
+ except:
+ pass
+ else:
+ if image and image.mode in ("1", "L"):
+ break
+ else:
+ raise IOError("cannot find glyph data file")
+
+ self.file = fullname
+
+ return self._load_pilfont_data(file, image)
+
+ def _load_pilfont_data(self, file, image):
+
+ # read PILfont header
+ if file.readline() != "PILfont\n":
+ raise SyntaxError("Not a PILfont file")
+ d = string.split(file.readline(), ";")
+ self.info = [] # FIXME: should be a dictionary
+ s = file.readline()
+ while s and s != "DATA\n":
+ self.info.append(s)
+
+ # read PILfont metrics
+ data = file.read(256*20)
+
+ # check image
+ if image.mode not in ("1", "L"):
+ raise TypeError("invalid font image mode")
+
+ image.load()
+
+ self.font = Image.core.font(image.im, data)
+
+ # delegate critical operations to internal type
+ self.getsize = self.font.getsize
+ self.getmask = self.font.getmask
+
+##
+# Wrapper for FreeType fonts. Application code should use the
+# <b>truetype</b> factory function to create font objects.
+
+class FreeTypeFont:
+ "FreeType font wrapper (requires _imagingft service)"
+
+ def __init__(self, file, size, index=0, encoding=""):
+ # FIXME: use service provider instead
+ import _imagingft
+ self.font = _imagingft.getfont(file, size, index, encoding)
+
+ def getname(self):
+ return self.font.family, self.font.style
+
+ def getmetrics(self):
+ return self.font.ascent, self.font.descent
+
+ def getsize(self, text):
+ return self.font.getsize(text)[0]
+
+ def getmask(self, text, mode=""):
+ return self.getmask2(text, mode)[0]
+
+ def getmask2(self, text, mode="", fill=Image.core.fill):
+ size, offset = self.font.getsize(text)
+ im = fill("L", size, 0)
+ self.font.render(text, im.id, mode=="1")
+ return im, offset
+
+##
+# Wrapper that creates a transposed font from any existing font
+# object.
+#
+# @param font A font object.
+# @param orientation An optional orientation. If given, this should
+# be one of Image.FLIP_LEFT_RIGHT, Image.FLIP_TOP_BOTTOM,
+# Image.ROTATE_90, Image.ROTATE_180, or Image.ROTATE_270.
+
+class TransposedFont:
+ "Wrapper for writing rotated or mirrored text"
+
+ def __init__(self, font, orientation=None):
+ self.font = font
+ self.orientation = orientation # any 'transpose' argument, or None
+
+ def getsize(self, text):
+ w, h = self.font.getsize(text)
+ if self.orientation in (Image.ROTATE_90, Image.ROTATE_270):
+ return h, w
+ return w, h
+
+ def getmask(self, text, mode=""):
+ im = self.font.getmask(text, mode)
+ if self.orientation is not None:
+ return im.transpose(self.orientation)
+ return im
+
+##
+# Load font file. This function loads a font object from the given
+# bitmap font file, and returns the corresponding font object.
+#
+# @param filename Name of font file.
+# @return A font object.
+# @exception IOError If the file could not be read.
+
+def load(filename):
+ "Load a font file."
+ f = ImageFont()
+ f._load_pilfont(filename)
+ return f
+
+##
+# Load a TrueType or OpenType font file, and create a font object.
+# This function loads a font object from the given file, and creates
+# a font object for a font of the given size.
+# <p>
+# This function requires the _imagingft service.
+#
+# @param filename A truetype font file. Under Windows, if the file
+# is not found in this filename, the loader also looks in Windows
+# <b>fonts</b> directory
+# @param size The requested size, in points.
+# @param index Which font face to load (default is first available face).
+# @param encoding Which font encoding to use (default is Unicode). Common
+# encodings are "unic" (Unicode), "symb" (Microsoft Symbol), "ADOB"
+# (Adobe Standard), "ADBE" (Adobe Expert), and "armn" (Apple Roman).
+# See the FreeType documentation for more information.
+# @return A font object.
+# @exception IOError If the file could not be read.
+
+def truetype(filename, size, index=0, encoding=""):
+ "Load a truetype font file."
+ try:
+ return FreeTypeFont(filename, size, index, encoding)
+ except IOError:
+ if sys.platform == "win32":
+ # check the windows font repository
+ # NOTE: must use uppercase WINDIR, to work around bugs in
+ # 1.5.2's os.environ.get()
+ windir = os.environ.get("WINDIR")
+ if windir:
+ filename = os.path.join(windir, "fonts", filename)
+ return FreeTypeFont(filename, size, index, encoding)
+ raise
+
+##
+# Load font file. Same as load, but searches for a bitmap font along
+# the Python path.
+#
+# @param filename Name of font file.
+# @return A font object.
+# @exception IOError If the file could not be read.
+# @see #load
+
+def load_path(filename):
+ "Load a font file, searching along the Python path."
+ for dir in sys.path:
+ if Image.isDirectory(dir):
+ try:
+ return load(os.path.join(dir, filename))
+ except IOError:
+ pass
+ raise IOError("cannot find font file")
+
+##
+# Load a (probably rather ugly) default font.
+#
+# @return A font object.
+
+def load_default():
+ "Load a default font."
+ from StringIO import StringIO
+ import base64
+ f = ImageFont()
+ f._load_pilfont_data(
+ # courB08
+ StringIO(base64.decodestring('''
+UElMZm9udAo7Ozs7OzsxMDsKREFUQQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA//8AAQAAAAAAAAABAAEA
+BgAAAAH/+gADAAAAAQAAAAMABgAGAAAAAf/6AAT//QADAAAABgADAAYAAAAA//kABQABAAYAAAAL
+AAgABgAAAAD/+AAFAAEACwAAABAACQAGAAAAAP/5AAUAAAAQAAAAFQAHAAYAAP////oABQAAABUA
+AAAbAAYABgAAAAH/+QAE//wAGwAAAB4AAwAGAAAAAf/5AAQAAQAeAAAAIQAIAAYAAAAB//kABAAB
+ACEAAAAkAAgABgAAAAD/+QAE//0AJAAAACgABAAGAAAAAP/6AAX//wAoAAAALQAFAAYAAAAB//8A
+BAACAC0AAAAwAAMABgAAAAD//AAF//0AMAAAADUAAQAGAAAAAf//AAMAAAA1AAAANwABAAYAAAAB
+//kABQABADcAAAA7AAgABgAAAAD/+QAFAAAAOwAAAEAABwAGAAAAAP/5AAYAAABAAAAARgAHAAYA
+AAAA//kABQAAAEYAAABLAAcABgAAAAD/+QAFAAAASwAAAFAABwAGAAAAAP/5AAYAAABQAAAAVgAH
+AAYAAAAA//kABQAAAFYAAABbAAcABgAAAAD/+QAFAAAAWwAAAGAABwAGAAAAAP/5AAUAAABgAAAA
+ZQAHAAYAAAAA//kABQAAAGUAAABqAAcABgAAAAD/+QAFAAAAagAAAG8ABwAGAAAAAf/8AAMAAABv
+AAAAcQAEAAYAAAAA//wAAwACAHEAAAB0AAYABgAAAAD/+gAE//8AdAAAAHgABQAGAAAAAP/7AAT/
+/gB4AAAAfAADAAYAAAAB//oABf//AHwAAACAAAUABgAAAAD/+gAFAAAAgAAAAIUABgAGAAAAAP/5
+AAYAAQCFAAAAiwAIAAYAAP////oABgAAAIsAAACSAAYABgAA////+gAFAAAAkgAAAJgABgAGAAAA
+AP/6AAUAAACYAAAAnQAGAAYAAP////oABQAAAJ0AAACjAAYABgAA////+gAFAAAAowAAAKkABgAG
+AAD////6AAUAAACpAAAArwAGAAYAAAAA//oABQAAAK8AAAC0AAYABgAA////+gAGAAAAtAAAALsA
+BgAGAAAAAP/6AAQAAAC7AAAAvwAGAAYAAP////oABQAAAL8AAADFAAYABgAA////+gAGAAAAxQAA
+AMwABgAGAAD////6AAUAAADMAAAA0gAGAAYAAP////oABQAAANIAAADYAAYABgAA////+gAGAAAA
+2AAAAN8ABgAGAAAAAP/6AAUAAADfAAAA5AAGAAYAAP////oABQAAAOQAAADqAAYABgAAAAD/+gAF
+AAEA6gAAAO8ABwAGAAD////6AAYAAADvAAAA9gAGAAYAAAAA//oABQAAAPYAAAD7AAYABgAA////
++gAFAAAA+wAAAQEABgAGAAD////6AAYAAAEBAAABCAAGAAYAAP////oABgAAAQgAAAEPAAYABgAA
+////+gAGAAABDwAAARYABgAGAAAAAP/6AAYAAAEWAAABHAAGAAYAAP////oABgAAARwAAAEjAAYA
+BgAAAAD/+gAFAAABIwAAASgABgAGAAAAAf/5AAQAAQEoAAABKwAIAAYAAAAA//kABAABASsAAAEv
+AAgABgAAAAH/+QAEAAEBLwAAATIACAAGAAAAAP/5AAX//AEyAAABNwADAAYAAAAAAAEABgACATcA
+AAE9AAEABgAAAAH/+QAE//wBPQAAAUAAAwAGAAAAAP/7AAYAAAFAAAABRgAFAAYAAP////kABQAA
+AUYAAAFMAAcABgAAAAD/+wAFAAABTAAAAVEABQAGAAAAAP/5AAYAAAFRAAABVwAHAAYAAAAA//sA
+BQAAAVcAAAFcAAUABgAAAAD/+QAFAAABXAAAAWEABwAGAAAAAP/7AAYAAgFhAAABZwAHAAYAAP//
+//kABQAAAWcAAAFtAAcABgAAAAD/+QAGAAABbQAAAXMABwAGAAAAAP/5AAQAAgFzAAABdwAJAAYA
+AP////kABgAAAXcAAAF+AAcABgAAAAD/+QAGAAABfgAAAYQABwAGAAD////7AAUAAAGEAAABigAF
+AAYAAP////sABQAAAYoAAAGQAAUABgAAAAD/+wAFAAABkAAAAZUABQAGAAD////7AAUAAgGVAAAB
+mwAHAAYAAAAA//sABgACAZsAAAGhAAcABgAAAAD/+wAGAAABoQAAAacABQAGAAAAAP/7AAYAAAGn
+AAABrQAFAAYAAAAA//kABgAAAa0AAAGzAAcABgAA////+wAGAAABswAAAboABQAGAAD////7AAUA
+AAG6AAABwAAFAAYAAP////sABgAAAcAAAAHHAAUABgAAAAD/+wAGAAABxwAAAc0ABQAGAAD////7
+AAYAAgHNAAAB1AAHAAYAAAAA//sABQAAAdQAAAHZAAUABgAAAAH/+QAFAAEB2QAAAd0ACAAGAAAA
+Av/6AAMAAQHdAAAB3gAHAAYAAAAA//kABAABAd4AAAHiAAgABgAAAAD/+wAF//0B4gAAAecAAgAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAB
+//sAAwACAecAAAHpAAcABgAAAAD/+QAFAAEB6QAAAe4ACAAGAAAAAP/5AAYAAAHuAAAB9AAHAAYA
+AAAA//oABf//AfQAAAH5AAUABgAAAAD/+QAGAAAB+QAAAf8ABwAGAAAAAv/5AAMAAgH/AAACAAAJ
+AAYAAAAA//kABQABAgAAAAIFAAgABgAAAAH/+gAE//sCBQAAAggAAQAGAAAAAP/5AAYAAAIIAAAC
+DgAHAAYAAAAB//kABf/+Ag4AAAISAAUABgAA////+wAGAAACEgAAAhkABQAGAAAAAP/7AAX//gIZ
+AAACHgADAAYAAAAA//wABf/9Ah4AAAIjAAEABgAAAAD/+QAHAAACIwAAAioABwAGAAAAAP/6AAT/
++wIqAAACLgABAAYAAAAA//kABP/8Ai4AAAIyAAMABgAAAAD/+gAFAAACMgAAAjcABgAGAAAAAf/5
+AAT//QI3AAACOgAEAAYAAAAB//kABP/9AjoAAAI9AAQABgAAAAL/+QAE//sCPQAAAj8AAgAGAAD/
+///7AAYAAgI/AAACRgAHAAYAAAAA//kABgABAkYAAAJMAAgABgAAAAH//AAD//0CTAAAAk4AAQAG
+AAAAAf//AAQAAgJOAAACUQADAAYAAAAB//kABP/9AlEAAAJUAAQABgAAAAH/+QAF//4CVAAAAlgA
+BQAGAAD////7AAYAAAJYAAACXwAFAAYAAP////kABgAAAl8AAAJmAAcABgAA////+QAGAAACZgAA
+Am0ABwAGAAD////5AAYAAAJtAAACdAAHAAYAAAAA//sABQACAnQAAAJ5AAcABgAA////9wAGAAAC
+eQAAAoAACQAGAAD////3AAYAAAKAAAAChwAJAAYAAP////cABgAAAocAAAKOAAkABgAA////9wAG
+AAACjgAAApUACQAGAAD////4AAYAAAKVAAACnAAIAAYAAP////cABgAAApwAAAKjAAkABgAA////
++gAGAAACowAAAqoABgAGAAAAAP/6AAUAAgKqAAACrwAIAAYAAP////cABQAAAq8AAAK1AAkABgAA
+////9wAFAAACtQAAArsACQAGAAD////3AAUAAAK7AAACwQAJAAYAAP////gABQAAAsEAAALHAAgA
+BgAAAAD/9wAEAAACxwAAAssACQAGAAAAAP/3AAQAAALLAAACzwAJAAYAAAAA//cABAAAAs8AAALT
+AAkABgAAAAD/+AAEAAAC0wAAAtcACAAGAAD////6AAUAAALXAAAC3QAGAAYAAP////cABgAAAt0A
+AALkAAkABgAAAAD/9wAFAAAC5AAAAukACQAGAAAAAP/3AAUAAALpAAAC7gAJAAYAAAAA//cABQAA
+Au4AAALzAAkABgAAAAD/9wAFAAAC8wAAAvgACQAGAAAAAP/4AAUAAAL4AAAC/QAIAAYAAAAA//oA
+Bf//Av0AAAMCAAUABgAA////+gAGAAADAgAAAwkABgAGAAD////3AAYAAAMJAAADEAAJAAYAAP//
+//cABgAAAxAAAAMXAAkABgAA////9wAGAAADFwAAAx4ACQAGAAD////4AAYAAAAAAAoABwASAAYA
+AP////cABgAAAAcACgAOABMABgAA////+gAFAAAADgAKABQAEAAGAAD////6AAYAAAAUAAoAGwAQ
+AAYAAAAA//gABgAAABsACgAhABIABgAAAAD/+AAGAAAAIQAKACcAEgAGAAAAAP/4AAYAAAAnAAoA
+LQASAAYAAAAA//gABgAAAC0ACgAzABIABgAAAAD/+QAGAAAAMwAKADkAEQAGAAAAAP/3AAYAAAA5
+AAoAPwATAAYAAP////sABQAAAD8ACgBFAA8ABgAAAAD/+wAFAAIARQAKAEoAEQAGAAAAAP/4AAUA
+AABKAAoATwASAAYAAAAA//gABQAAAE8ACgBUABIABgAAAAD/+AAFAAAAVAAKAFkAEgAGAAAAAP/5
+AAUAAABZAAoAXgARAAYAAAAA//gABgAAAF4ACgBkABIABgAAAAD/+AAGAAAAZAAKAGoAEgAGAAAA
+AP/4AAYAAABqAAoAcAASAAYAAAAA//kABgAAAHAACgB2ABEABgAAAAD/+AAFAAAAdgAKAHsAEgAG
+AAD////4AAYAAAB7AAoAggASAAYAAAAA//gABQAAAIIACgCHABIABgAAAAD/+AAFAAAAhwAKAIwA
+EgAGAAAAAP/4AAUAAACMAAoAkQASAAYAAAAA//gABQAAAJEACgCWABIABgAAAAD/+QAFAAAAlgAK
+AJsAEQAGAAAAAP/6AAX//wCbAAoAoAAPAAYAAAAA//oABQABAKAACgClABEABgAA////+AAGAAAA
+pQAKAKwAEgAGAAD////4AAYAAACsAAoAswASAAYAAP////gABgAAALMACgC6ABIABgAA////+QAG
+AAAAugAKAMEAEQAGAAD////4AAYAAgDBAAoAyAAUAAYAAP////kABQACAMgACgDOABMABgAA////
++QAGAAIAzgAKANUAEw==
+''')), Image.open(StringIO(base64.decodestring('''
+iVBORw0KGgoAAAANSUhEUgAAAx4AAAAUAQAAAAArMtZoAAAEwElEQVR4nABlAJr/AHVE4czCI/4u
+Mc4b7vuds/xzjz5/3/7u/n9vMe7vnfH/9++vPn/xyf5zhxzjt8GHw8+2d83u8x27199/nxuQ6Od9
+M43/5z2I+9n9ZtmDBwMQECDRQw/eQIQohJXxpBCNVE6QCCAAAAD//wBlAJr/AgALyj1t/wINwq0g
+LeNZUworuN1cjTPIzrTX6ofHWeo3v336qPzfEwRmBnHTtf95/fglZK5N0PDgfRTslpGBvz7LFc4F
+IUXBWQGjQ5MGCx34EDFPwXiY4YbYxavpnhHFrk14CDAAAAD//wBlAJr/AgKqRooH2gAgPeggvUAA
+Bu2WfgPoAwzRAABAAAAAAACQgLz/3Uv4Gv+gX7BJgDeeGP6AAAD1NMDzKHD7ANWr3loYbxsAD791
+NAADfcoIDyP44K/jv4Y63/Z+t98Ovt+ub4T48LAAAAD//wBlAJr/AuplMlADJAAAAGuAphWpqhMx
+in0A/fRvAYBABPgBwBUgABBQ/sYAyv9g0bCHgOLoGAAAAAAAREAAwI7nr0ArYpow7aX8//9LaP/9
+SjdavWA8ePHeBIKB//81/83ndznOaXx379wAAAD//wBlAJr/AqDxW+D3AABAAbUh/QMnbQag/gAY
+AYDAAACgtgD/gOqAAAB5IA/8AAAk+n9w0AAA8AAAmFRJuPo27ciC0cD5oeW4E7KA/wD3ECMAn2tt
+y8PgwH8AfAxFzC0JzeAMtratAsC/ffwAAAD//wBlAJr/BGKAyCAA4AAAAvgeYTAwHd1kmQF5chkG
+ABoMIHcL5xVpTfQbUqzlAAAErwAQBgAAEOClA5D9il08AEh/tUzdCBsXkbgACED+woQg8Si9VeqY
+lODCn7lmF6NhnAEYgAAA/NMIAAAAAAD//2JgjLZgVGBg5Pv/Tvpc8hwGBjYGJADjHDrAwPzAjv/H
+/Wf3PzCwtzcwHmBgYGcwbZz8wHaCAQMDOwMDQ8MCBgYOC3W7mp+f0w+wHOYxO3OG+e376hsMZjk3
+AAAAAP//YmCMY2A4wMAIN5e5gQETPD6AZisDAwMDgzSDAAPjByiHcQMDAwMDg1nOze1lByRu5/47
+c4859311AYNZzg0AAAAA//9iYGDBYihOIIMuwIjGL39/fwffA8b//xv/P2BPtzzHwCBjUQAAAAD/
+/yLFBrIBAAAA//9i1HhcwdhizX7u8NZNzyLbvT97bfrMf/QHI8evOwcSqGUJAAAA//9iYBB81iSw
+pEE170Qrg5MIYydHqwdDQRMrAwcVrQAAAAD//2J4x7j9AAMDn8Q/BgYLBoaiAwwMjPdvMDBYM1Tv
+oJodAAAAAP//Yqo/83+dxePWlxl3npsel9lvLfPcqlE9725C+acfVLMEAAAA//9i+s9gwCoaaGMR
+evta/58PTEWzr21hufPjA8N+qlnBwAAAAAD//2JiWLci5v1+HmFXDqcnULE/MxgYGBj+f6CaJQAA
+AAD//2Ji2FrkY3iYpYC5qDeGgeEMAwPDvwQBBoYvcTwOVLMEAAAA//9isDBgkP///0EOg9z35v//
+Gc/eeW7BwPj5+QGZhANUswMAAAD//2JgqGBgYGBgqEMXlvhMPUsAAAAA//8iYDd1AAAAAP//AwDR
+w7IkEbzhVQAAAABJRU5ErkJggg==
+'''))))
+ return f
+
+if __name__ == "__main__":
+ # create font data chunk for embedding
+ import base64, os, sys
+ font = "../Images/courB08"
+ print " f._load_pilfont_data("
+ print " # %s" % os.path.basename(font)
+ print " StringIO(base64.decodestring('''"
+ base64.encode(open(font + ".pil", "rb"), sys.stdout)
+ print "''')), Image.open(StringIO(base64.decodestring('''"
+ base64.encode(open(font + ".pbm", "rb"), sys.stdout)
+ print "'''))))"
diff --git a/Imaging/PIL/ImageGL.py b/Imaging/PIL/ImageGL.py
new file mode 100644
index 0000000..482f42d
--- /dev/null
+++ b/Imaging/PIL/ImageGL.py
@@ -0,0 +1,28 @@
+#
+# The Python Imaging Library.
+# $Id: ImageGL.py 2438 2005-05-25 21:09:48Z Fredrik $
+#
+# OpenGL pixmap/texture interface (requires imToolkit OpenGL extensions)
+#
+# History:
+# 2003-09-13 fl Added
+#
+# Copyright (c) Secret Labs AB 2003.
+#
+# See the README file for information on usage and redistribution.
+#
+
+##
+# OpenGL pixmap/texture interface (requires imToolkit OpenGL
+# extensions.)
+##
+
+import _imaginggl
+
+##
+# Texture factory.
+
+class TextureFactory:
+ pass # overwritten by the _imaginggl module
+
+from _imaginggl import *
diff --git a/Imaging/PIL/ImageGrab.py b/Imaging/PIL/ImageGrab.py
new file mode 100644
index 0000000..ecbfbac
--- /dev/null
+++ b/Imaging/PIL/ImageGrab.py
@@ -0,0 +1,71 @@
+#
+# The Python Imaging Library
+# $Id: ImageGrab.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# screen grabber (windows only)
+#
+# History:
+# 2001-04-26 fl created
+# 2001-09-17 fl use builtin driver, if present
+# 2002-11-19 fl added grabclipboard support
+#
+# Copyright (c) 2001-2002 by Secret Labs AB
+# Copyright (c) 2001-2002 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image
+
+##
+# (New in 1.1.3) The <b>ImageGrab</b> module can be used to copy
+# the contents of the screen to a PIL image memory.
+# <p>
+# The current version works on Windows only.</p>
+#
+# @since 1.1.3
+##
+
+try:
+ # built-in driver (1.1.3 and later)
+ grabber = Image.core.grabscreen
+except AttributeError:
+ # stand-alone driver (pil plus)
+ import _grabscreen
+ grabber = _grabscreen.grab
+
+##
+# (New in 1.1.3) Take a snapshot of the screen. The pixels inside the
+# bounding box are returned as an "RGB" image. If the bounding box is
+# omitted, the entire screen is copied.
+#
+# @param bbox What region to copy. Default is the entire screen.
+# @return An image
+# @since 1.1.3
+
+def grab(bbox=None):
+ size, data = grabber()
+ im = Image.fromstring(
+ "RGB", size, data,
+ # RGB, 32-bit line padding, origo in lower left corner
+ "raw", "BGR", (size[0]*3 + 3) & -4, -1
+ )
+ if bbox:
+ im = im.crop(bbox)
+ return im
+
+##
+# (New in 1.1.4) Take a snapshot of the clipboard image, if any.
+#
+# @return An image, a list of filenames, or None if the clipboard does
+# not contain image data or filenames. Note that if a list is
+# returned, the filenames may not represent image files.
+# @since 1.1.4
+
+def grabclipboard():
+ debug = 0 # temporary interface
+ data = Image.core.grabclipboard(debug)
+ if Image.isStringType(data):
+ import BmpImagePlugin, StringIO
+ return BmpImagePlugin.DibImageFile(StringIO.StringIO(data))
+ return data
diff --git a/Imaging/PIL/ImageMath.py b/Imaging/PIL/ImageMath.py
new file mode 100644
index 0000000..117a5ae
--- /dev/null
+++ b/Imaging/PIL/ImageMath.py
@@ -0,0 +1,207 @@
+#
+# The Python Imaging Library
+# $Id: ImageMath.py 2508 2005-09-12 19:01:03Z fredrik $
+#
+# a simple math add-on for the Python Imaging Library
+#
+# History:
+# 1999-02-15 fl Original PIL Plus release
+# 2005-05-05 fl Simplified and cleaned up for PIL 1.1.6
+# 2005-09-12 fl Fixed int() and float() for Python 2.4.1
+#
+# Copyright (c) 1999-2005 by Secret Labs AB
+# Copyright (c) 2005 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image
+import _imagingmath
+
+VERBOSE = 0
+
+def _isconstant(v):
+ return isinstance(v, type(0)) or isinstance(v, type(0.0))
+
+class _Operand:
+ # wraps an image operand, providing standard operators
+
+ def __init__(self, im):
+ self.im = im
+
+ def __fixup(self, im1):
+ # convert image to suitable mode
+ if isinstance(im1, _Operand):
+ # argument was an image.
+ if im1.im.mode in ("1", "L"):
+ return im1.im.convert("I")
+ elif im1.im.mode in ("I", "F"):
+ return im1.im
+ else:
+ raise ValueError, "unsupported mode: %s" % im1.im.mode
+ else:
+ # argument was a constant
+ if _isconstant(im1) and self.im.mode in ("1", "L", "I"):
+ return Image.new("I", self.im.size, im1)
+ else:
+ return Image.new("F", self.im.size, im1)
+
+ def apply(self, op, im1, im2=None, mode=None):
+ im1 = self.__fixup(im1)
+ if im2 is None:
+ # unary operation
+ out = Image.new(mode or im1.mode, im1.size, None)
+ im1.load()
+ try:
+ op = getattr(_imagingmath, op+"_"+im1.mode)
+ except AttributeError:
+ raise TypeError, "bad operand type for '%s'" % op
+ _imagingmath.unop(op, out.im.id, im1.im.id)
+ else:
+ # binary operation
+ im2 = self.__fixup(im2)
+ if im1.mode != im2.mode:
+ # convert both arguments to floating point
+ if im1.mode != "F": im1 = im1.convert("F")
+ if im2.mode != "F": im2 = im2.convert("F")
+ if im1.mode != im2.mode:
+ raise ValueError, "mode mismatch"
+ if im1.size != im2.size:
+ # crop both arguments to a common size
+ size = (min(im1.size[0], im2.size[0]),
+ min(im1.size[1], im2.size[1]))
+ if im1.size != size: im1 = im1.crop((0, 0) + size)
+ if im2.size != size: im2 = im2.crop((0, 0) + size)
+ out = Image.new(mode or im1.mode, size, None)
+ else:
+ out = Image.new(mode or im1.mode, im1.size, None)
+ im1.load(); im2.load()
+ try:
+ op = getattr(_imagingmath, op+"_"+im1.mode)
+ except AttributeError:
+ raise TypeError, "bad operand type for '%s'" % op
+ _imagingmath.binop(op, out.im.id, im1.im.id, im2.im.id)
+ return _Operand(out)
+
+ # unary operators
+ def __nonzero__(self):
+ # an image is "true" if it contains at least one non-zero pixel
+ return self.im.getbbox() is not None
+ def __abs__(self):
+ return self.apply("abs", self)
+ def __pos__(self):
+ return self
+ def __neg__(self):
+ return self.apply("neg", self)
+
+ # binary operators
+ def __add__(self, other):
+ return self.apply("add", self, other)
+ def __radd__(self, other):
+ return self.apply("add", other, self)
+ def __sub__(self, other):
+ return self.apply("sub", self, other)
+ def __rsub__(self, other):
+ return self.apply("sub", other, self)
+ def __mul__(self, other):
+ return self.apply("mul", self, other)
+ def __rmul__(self, other):
+ return self.apply("mul", other, self)
+ def __div__(self, other):
+ return self.apply("div", self, other)
+ def __rdiv__(self, other):
+ return self.apply("div", other, self)
+ def __mod__(self, other):
+ return self.apply("mod", self, other)
+ def __rmod__(self, other):
+ return self.apply("mod", other, self)
+ def __pow__(self, other):
+ return self.apply("pow", self, other)
+ def __rpow__(self, other):
+ return self.apply("pow", other, self)
+
+ # bitwise
+ def __invert__(self):
+ return self.apply("invert", self)
+ def __and__(self, other):
+ return self.apply("and", self, other)
+ def __rand__(self, other):
+ return self.apply("and", other, self)
+ def __or__(self, other):
+ return self.apply("or", self, other)
+ def __ror__(self, other):
+ return self.apply("or", other, self)
+ def __xor__(self, other):
+ return self.apply("xor", self, other)
+ def __rxor__(self, other):
+ return self.apply("xor", other, self)
+ def __lshift__(self, other):
+ return self.apply("lshift", self, other)
+ def __rshift__(self, other):
+ return self.apply("rshift", self, other)
+
+ # logical
+ def __eq__(self, other):
+ return self.apply("eq", self, other)
+ def __ne__(self, other):
+ return self.apply("ne", self, other)
+ def __lt__(self, other):
+ return self.apply("lt", self, other)
+ def __le__(self, other):
+ return self.apply("le", self, other)
+ def __gt__(self, other):
+ return self.apply("gt", self, other)
+ def __ge__(self, other):
+ return self.apply("ge", self, other)
+
+# conversions
+def imagemath_int(self):
+ return _Operand(self.im.convert("I"))
+def imagemath_float(self):
+ return _Operand(self.im.convert("F"))
+
+# logical
+def imagemath_equal(self, other):
+ return self.apply("eq", self, other, mode="I")
+def imagemath_notequal(self, other):
+ return self.apply("ne", self, other, mode="I")
+
+def imagemath_min(self, other):
+ return self.apply("min", self, other)
+def imagemath_max(self, other):
+ return self.apply("max", self, other)
+
+def imagemath_convert(self, mode):
+ return _Operand(self.im.convert(mode))
+
+ops = {}
+for k, v in globals().items():
+ if k[:10] == "imagemath_":
+ ops[k[10:]] = v
+
+##
+# Evaluates an image expression.
+#
+# @param expression A string containing a Python-style expression.
+# @keyparam options Values to add to the evaluation context. You
+# can either use a dictionary, or one or more keyword arguments.
+# @return The evaluated expression. This is usually an image object,
+# but can also be an integer, a floating point value, or a pixel
+# tuple, depending on the expression.
+
+def eval(expression, _dict={}, **kw):
+
+ # build execution namespace
+ args = ops.copy()
+ args.update(_dict)
+ args.update(kw)
+ for k, v in args.items():
+ if hasattr(v, "im"):
+ args[k] = _Operand(v)
+
+ import __builtin__
+ out =__builtin__.eval(expression, args)
+ try:
+ return out.im
+ except AttributeError:
+ return out
diff --git a/Imaging/PIL/ImageMode.py b/Imaging/PIL/ImageMode.py
new file mode 100644
index 0000000..87a0e5a
--- /dev/null
+++ b/Imaging/PIL/ImageMode.py
@@ -0,0 +1,46 @@
+#
+# The Python Imaging Library.
+# $Id: /work/modules/pil/PIL/ImageFilter.py 486 2004-10-06T08:55:20.930352Z fredrik $
+#
+# standard mode descriptors
+#
+# History:
+# 2006-03-20 fl Added
+#
+# Copyright (c) 2006 by Secret Labs AB.
+# Copyright (c) 2006 by Fredrik Lundh.
+#
+# See the README file for information on usage and redistribution.
+#
+
+# mode descriptor cache
+_modes = {}
+
+##
+# Wrapper for mode strings.
+
+class ModeDescriptor:
+
+ def __init__(self, mode, bands, basemode, basetype):
+ self.mode = mode
+ self.bands = bands
+ self.basemode = basemode
+ self.basetype = basetype
+
+ def __str__(self):
+ return self.mode
+
+##
+# Gets a mode descriptor for the given mode.
+
+def getmode(mode):
+ if not _modes:
+ # initialize mode cache
+ import Image
+ # core modes
+ for m, (basemode, basetype, bands) in Image._MODEINFO.items():
+ _modes[m] = ModeDescriptor(m, bands, basemode, basetype)
+ # extra experimental modes
+ _modes["LA"] = ModeDescriptor("LA", ("L", "A"), "L", "L")
+ _modes["PA"] = ModeDescriptor("PA", ("P", "A"), "RGB", "L")
+ return _modes[mode]
diff --git a/Imaging/PIL/ImageOps.py b/Imaging/PIL/ImageOps.py
new file mode 100644
index 0000000..89b5e72
--- /dev/null
+++ b/Imaging/PIL/ImageOps.py
@@ -0,0 +1,408 @@
+#
+# The Python Imaging Library.
+# $Id: ImageOps.py 2760 2006-06-19 13:31:40Z fredrik $
+#
+# standard image operations
+#
+# History:
+# 2001-10-20 fl Created
+# 2001-10-23 fl Added autocontrast operator
+# 2001-12-18 fl Added Kevin's fit operator
+# 2004-03-14 fl Fixed potential division by zero in equalize
+# 2005-05-05 fl Fixed equalize for low number of values
+#
+# Copyright (c) 2001-2004 by Secret Labs AB
+# Copyright (c) 2001-2004 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image
+import operator
+
+##
+# (New in 1.1.3) The <b>ImageOps</b> module contains a number of
+# 'ready-made' image processing operations. This module is somewhat
+# experimental, and most operators only work on L and RGB images.
+#
+# @since 1.1.3
+##
+
+#
+# helpers
+
+def _border(border):
+ if type(border) is type(()):
+ if len(border) == 2:
+ left, top = right, bottom = border
+ elif len(border) == 4:
+ left, top, right, bottom = border
+ else:
+ left = top = right = bottom = border
+ return left, top, right, bottom
+
+def _color(color, mode):
+ if Image.isStringType(color):
+ import ImageColor
+ color = ImageColor.getcolor(color, mode)
+ return color
+
+def _lut(image, lut):
+ if image.mode == "P":
+ # FIXME: apply to lookup table, not image data
+ raise NotImplementedError("mode P support coming soon")
+ elif image.mode in ("L", "RGB"):
+ if image.mode == "RGB" and len(lut) == 256:
+ lut = lut + lut + lut
+ return image.point(lut)
+ else:
+ raise IOError, "not supported for this image mode"
+
+#
+# actions
+
+##
+# Maximize (normalize) image contrast. This function calculates a
+# histogram of the input image, removes <i>cutoff</i> percent of the
+# lightest and darkest pixels from the histogram, and remaps the image
+# so that the darkest pixel becomes black (0), and the lightest
+# becomes white (255).
+#
+# @param image The image to process.
+# @param cutoff How many percent to cut off from the histogram.
+# @param ignore The background pixel value (use None for no background).
+# @return An image.
+
+def autocontrast(image, cutoff=0, ignore=None):
+ "Maximize image contrast, based on histogram"
+ histogram = image.histogram()
+ lut = []
+ for layer in range(0, len(histogram), 256):
+ h = histogram[layer:layer+256]
+ if ignore is not None:
+ # get rid of outliers
+ try:
+ h[ignore] = 0
+ except TypeError:
+ # assume sequence
+ for ix in ignore:
+ h[ix] = 0
+ if cutoff:
+ # cut off pixels from both ends of the histogram
+ # get number of pixels
+ n = 0
+ for ix in range(256):
+ n = n + h[ix]
+ # remove cutoff% pixels from the low end
+ cut = n * cutoff / 100
+ for lo in range(256):
+ if cut > h[lo]:
+ cut = cut - h[lo]
+ h[lo] = 0
+ else:
+ h[lo] = h[lo] - cut
+ cut = 0
+ if cut <= 0:
+ break
+ # remove cutoff% samples from the hi end
+ cut = n * cutoff / 100
+ for hi in range(255, -1, -1):
+ if cut > h[hi]:
+ cut = cut - h[hi]
+ h[hi] = 0
+ else:
+ h[hi] = h[hi] - cut
+ cut = 0
+ if cut <= 0:
+ break
+ # find lowest/highest samples after preprocessing
+ for lo in range(256):
+ if h[lo]:
+ break
+ for hi in range(255, -1, -1):
+ if h[hi]:
+ break
+ if hi <= lo:
+ # don't bother
+ lut.extend(range(256))
+ else:
+ scale = 255.0 / (hi - lo)
+ offset = -lo * scale
+ for ix in range(256):
+ ix = int(ix * scale + offset)
+ if ix < 0:
+ ix = 0
+ elif ix > 255:
+ ix = 255
+ lut.append(ix)
+ return _lut(image, lut)
+
+##
+# Colorize grayscale image. The <i>black</i> and <i>white</i>
+# arguments should be RGB tuples; this function calculates a colour
+# wedge mapping all black pixels in the source image to the first
+# colour, and all white pixels to the second colour.
+#
+# @param image The image to colourize.
+# @param black The colour to use for black input pixels.
+# @param white The colour to use for white input pixels.
+# @return An image.
+
+def colorize(image, black, white):
+ "Colorize a grayscale image"
+ assert image.mode == "L"
+ black = _color(black, "RGB")
+ white = _color(white, "RGB")
+ red = []; green = []; blue = []
+ for i in range(256):
+ red.append(black[0]+i*(white[0]-black[0])/255)
+ green.append(black[1]+i*(white[1]-black[1])/255)
+ blue.append(black[2]+i*(white[2]-black[2])/255)
+ image = image.convert("RGB")
+ return _lut(image, red + green + blue)
+
+##
+# Remove border from image. The same amount of pixels are removed
+# from all four sides. This function works on all image modes.
+#
+# @param image The image to crop.
+# @param border The number of pixels to remove.
+# @return An image.
+# @see Image#Image.crop
+
+def crop(image, border=0):
+ "Crop border off image"
+ left, top, right, bottom = _border(border)
+ return image.crop(
+ (left, top, image.size[0]-right, image.size[1]-bottom)
+ )
+
+##
+# Deform the image.
+#
+# @param image The image to deform.
+# @param deformer A deformer object. Any object that implements a
+# <b>getmesh</b> method can be used.
+# @param resample What resampling filter to use.
+# @return An image.
+
+def deform(image, deformer, resample=Image.BILINEAR):
+ "Deform image using the given deformer"
+ return image.transform(
+ image.size, Image.MESH, deformer.getmesh(image), resample
+ )
+
+##
+# Equalize the image histogram. This function applies a non-linear
+# mapping to the input image, in order to create a uniform
+# distribution of grayscale values in the output image.
+#
+# @param image The image to equalize.
+# @param mask An optional mask. If given, only the pixels selected by
+# the mask are included in the analysis.
+# @return An image.
+
+def equalize(image, mask=None):
+ "Equalize image histogram"
+ if image.mode == "P":
+ image = image.convert("RGB")
+ h = image.histogram(mask)
+ lut = []
+ for b in range(0, len(h), 256):
+ histo = filter(None, h[b:b+256])
+ if len(histo) <= 1:
+ lut.extend(range(256))
+ else:
+ step = (reduce(operator.add, histo) - histo[-1]) / 255
+ if not step:
+ lut.extend(range(256))
+ else:
+ n = step / 2
+ for i in range(256):
+ lut.append(n / step)
+ n = n + h[i+b]
+ return _lut(image, lut)
+
+##
+# Add border to the image
+#
+# @param image The image to expand.
+# @param border Border width, in pixels.
+# @param fill Pixel fill value (a colour value). Default is 0 (black).
+# @return An image.
+
+def expand(image, border=0, fill=0):
+ "Add border to image"
+ left, top, right, bottom = _border(border)
+ width = left + image.size[0] + right
+ height = top + image.size[1] + bottom
+ out = Image.new(image.mode, (width, height), _color(fill, image.mode))
+ out.paste(image, (left, top))
+ return out
+
+##
+# Returns a sized and cropped version of the image, cropped to the
+# requested aspect ratio and size.
+# <p>
+# The <b>fit</b> function was contributed by Kevin Cazabon.
+#
+# @param size The requested output size in pixels, given as a
+# (width, height) tuple.
+# @param method What resampling method to use. Default is Image.NEAREST.
+# @param bleed Remove a border around the outside of the image (from all
+# four edges. The value is a decimal percentage (use 0.01 for one
+# percent). The default value is 0 (no border).
+# @param centering Control the cropping position. Use (0.5, 0.5) for
+# center cropping (e.g. if cropping the width, take 50% off of the
+# left side, and therefore 50% off the right side). (0.0, 0.0)
+# will crop from the top left corner (i.e. if cropping the width,
+# take all of the crop off of the right side, and if cropping the
+# height, take all of it off the bottom). (1.0, 0.0) will crop
+# from the bottom left corner, etc. (i.e. if cropping the width,
+# take all of the crop off the left side, and if cropping the height
+# take none from the top, and therefore all off the bottom).
+# @return An image.
+
+def fit(image, size, method=Image.NEAREST, bleed=0.0, centering=(0.5, 0.5)):
+ """
+ This method returns a sized and cropped version of the image,
+ cropped to the aspect ratio and size that you request.
+ """
+
+ # by Kevin Cazabon, Feb 17/2000
+ # kevin@cazabon.com
+ # http://www.cazabon.com
+
+ # ensure inputs are valid
+ if type(centering) != type([]):
+ centering = [centering[0], centering[1]]
+
+ if centering[0] > 1.0 or centering[0] < 0.0:
+ centering [0] = 0.50
+ if centering[1] > 1.0 or centering[1] < 0.0:
+ centering[1] = 0.50
+
+ if bleed > 0.49999 or bleed < 0.0:
+ bleed = 0.0
+
+ # calculate the area to use for resizing and cropping, subtracting
+ # the 'bleed' around the edges
+
+ # number of pixels to trim off on Top and Bottom, Left and Right
+ bleedPixels = (
+ int((float(bleed) * float(image.size[0])) + 0.5),
+ int((float(bleed) * float(image.size[1])) + 0.5)
+ )
+
+ liveArea = (
+ bleedPixels[0], bleedPixels[1], image.size[0] - bleedPixels[0] - 1,
+ image.size[1] - bleedPixels[1] - 1
+ )
+
+ liveSize = (liveArea[2] - liveArea[0], liveArea[3] - liveArea[1])
+
+ # calculate the aspect ratio of the liveArea
+ liveAreaAspectRatio = float(liveSize[0])/float(liveSize[1])
+
+ # calculate the aspect ratio of the output image
+ aspectRatio = float(size[0]) / float(size[1])
+
+ # figure out if the sides or top/bottom will be cropped off
+ if liveAreaAspectRatio >= aspectRatio:
+ # liveArea is wider than what's needed, crop the sides
+ cropWidth = int((aspectRatio * float(liveSize[1])) + 0.5)
+ cropHeight = liveSize[1]
+ else:
+ # liveArea is taller than what's needed, crop the top and bottom
+ cropWidth = liveSize[0]
+ cropHeight = int((float(liveSize[0])/aspectRatio) + 0.5)
+
+ # make the crop
+ leftSide = int(liveArea[0] + (float(liveSize[0]-cropWidth) * centering[0]))
+ if leftSide < 0:
+ leftSide = 0
+ topSide = int(liveArea[1] + (float(liveSize[1]-cropHeight) * centering[1]))
+ if topSide < 0:
+ topSide = 0
+
+ out = image.crop(
+ (leftSide, topSide, leftSide + cropWidth, topSide + cropHeight)
+ )
+
+ # resize the image and return it
+ return out.resize(size, method)
+
+##
+# Flip the image vertically (top to bottom).
+#
+# @param image The image to flip.
+# @return An image.
+
+def flip(image):
+ "Flip image vertically"
+ return image.transpose(Image.FLIP_TOP_BOTTOM)
+
+##
+# Convert the image to grayscale.
+#
+# @param image The image to convert.
+# @return An image.
+
+def grayscale(image):
+ "Convert to grayscale"
+ return image.convert("L")
+
+##
+# Invert (negate) the image.
+#
+# @param image The image to invert.
+# @return An image.
+
+def invert(image):
+ "Invert image (negate)"
+ lut = []
+ for i in range(256):
+ lut.append(255-i)
+ return _lut(image, lut)
+
+##
+# Flip image horizontally (left to right).
+#
+# @param image The image to mirror.
+# @return An image.
+
+def mirror(image):
+ "Flip image horizontally"
+ return image.transpose(Image.FLIP_LEFT_RIGHT)
+
+##
+# Reduce the number of bits for each colour channel.
+#
+# @param image The image to posterize.
+# @param bits The number of bits to keep for each channel (1-8).
+# @return An image.
+
+def posterize(image, bits):
+ "Reduce the number of bits per color channel"
+ lut = []
+ mask = ~(2**(8-bits)-1)
+ for i in range(256):
+ lut.append(i & mask)
+ return _lut(image, lut)
+
+##
+# Invert all pixel values above a threshold.
+#
+# @param image The image to posterize.
+# @param threshold All pixels above this greyscale level are inverted.
+# @return An image.
+
+def solarize(image, threshold=128):
+ "Invert all values above threshold"
+ lut = []
+ for i in range(256):
+ if i < threshold:
+ lut.append(i)
+ else:
+ lut.append(255-i)
+ return _lut(image, lut)
diff --git a/Imaging/PIL/ImagePalette.py b/Imaging/PIL/ImagePalette.py
new file mode 100644
index 0000000..0e9a93a
--- /dev/null
+++ b/Imaging/PIL/ImagePalette.py
@@ -0,0 +1,161 @@
+#
+# The Python Imaging Library.
+# $Id: ImagePalette.py 2339 2005-03-25 08:02:17Z fredrik $
+#
+# image palette object
+#
+# History:
+# 1996-03-11 fl Rewritten.
+# 1997-01-03 fl Up and running.
+# 1997-08-23 fl Added load hack
+# 2001-04-16 fl Fixed randint shadow bug in random()
+#
+# Copyright (c) 1997-2001 by Secret Labs AB
+# Copyright (c) 1996-1997 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+import array
+import Image
+
+##
+# Colour palette wrapper for palette mapped images.
+
+class ImagePalette:
+ "Colour palette for palette mapped images"
+
+ def __init__(self, mode = "RGB", palette = None):
+ self.mode = mode
+ self.rawmode = None # if set, palette contains raw data
+ self.palette = palette or range(256)*len(self.mode)
+ self.colors = {}
+ self.dirty = None
+ if len(self.mode)*256 != len(self.palette):
+ raise ValueError, "wrong palette size"
+
+ def getdata(self):
+ # experimental: get palette contains in format suitable
+ # for the low-level im.putpalette primitive
+ if self.rawmode:
+ return self.rawmode, self.palette
+ return self.mode + ";L", self.tostring()
+
+ def tostring(self):
+ # experimental: convert palette to string
+ if self.rawmode:
+ raise ValueError("palette contains raw palette data")
+ if Image.isStringType(self.palette):
+ return self.palette
+ return array.array("B", self.palette).tostring()
+
+ def getcolor(self, color):
+ # experimental: given an rgb tuple, allocate palette entry
+ if self.rawmode:
+ raise ValueError("palette contains raw palette data")
+ if Image.isTupleType(color):
+ try:
+ return self.colors[color]
+ except KeyError:
+ # allocate new color slot
+ if Image.isStringType(self.palette):
+ self.palette = map(int, self.palette)
+ index = len(self.colors)
+ if index >= 256:
+ raise ValueError("cannot allocate more than 256 colors")
+ self.colors[color] = index
+ self.palette[index] = color[0]
+ self.palette[index+256] = color[1]
+ self.palette[index+512] = color[2]
+ self.dirty = 1
+ return index
+ else:
+ raise ValueError("unknown color specifier: %r" % color)
+
+ def save(self, fp):
+ # (experimental) save palette to text file
+ if self.rawmode:
+ raise ValueError("palette contains raw palette data")
+ if type(fp) == type(""):
+ fp = open(fp, "w")
+ fp.write("# Palette\n")
+ fp.write("# Mode: %s\n" % self.mode)
+ for i in range(256):
+ fp.write("%d" % i)
+ for j in range(i, len(self.palette), 256):
+ fp.write(" %d" % self.palette[j])
+ fp.write("\n")
+ fp.close()
+
+# --------------------------------------------------------------------
+# Internal
+
+def raw(rawmode, data):
+ palette = ImagePalette()
+ palette.rawmode = rawmode
+ palette.palette = data
+ palette.dirty = 1
+ return palette
+
+# --------------------------------------------------------------------
+# Factories
+
+def new(mode, data):
+ return Image.core.new_palette(mode, data)
+
+def negative(mode = "RGB"):
+ palette = range(256)
+ palette.reverse()
+ return ImagePalette(mode, palette * len(mode))
+
+def random(mode = "RGB"):
+ from random import randint
+ palette = map(lambda a, randint=randint:
+ randint(0, 255), [0]*256*len(mode))
+ return ImagePalette(mode, palette)
+
+def wedge(mode = "RGB"):
+ return ImagePalette(mode, range(256) * len(mode))
+
+def load(filename):
+
+ # FIXME: supports GIMP gradients only
+
+ fp = open(filename, "rb")
+
+ lut = None
+
+ if not lut:
+ try:
+ import GimpPaletteFile
+ fp.seek(0)
+ p = GimpPaletteFile.GimpPaletteFile(fp)
+ lut = p.getpalette()
+ except (SyntaxError, ValueError):
+ pass
+
+ if not lut:
+ try:
+ import GimpGradientFile
+ fp.seek(0)
+ p = GimpGradientFile.GimpGradientFile(fp)
+ lut = p.getpalette()
+ except (SyntaxError, ValueError):
+ pass
+
+ if not lut:
+ try:
+ import PaletteFile
+ fp.seek(0)
+ p = PaletteFile.PaletteFile(fp)
+ lut = p.getpalette()
+ except (SyntaxError, ValueError):
+ pass
+
+ if not lut:
+ raise IOError, "cannot load palette"
+
+ return lut # data, rawmode
+
+
+# add some psuedocolour palettes as well
diff --git a/Imaging/PIL/ImagePath.py b/Imaging/PIL/ImagePath.py
new file mode 100644
index 0000000..120a607
--- /dev/null
+++ b/Imaging/PIL/ImagePath.py
@@ -0,0 +1,71 @@
+#
+# The Python Imaging Library
+# $Id: ImagePath.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# path interface
+#
+# History:
+# 1996-11-04 fl Created
+# 2002-04-14 fl Added documentation stub class
+#
+# Copyright (c) Secret Labs AB 1997.
+# Copyright (c) Fredrik Lundh 1996.
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image
+
+##
+# Path wrapper.
+
+class Path:
+
+ ##
+ # Creates a path object.
+ #
+ # @param xy Sequence. The sequence can contain 2-tuples [(x, y), ...]
+ # or a flat list of numbers [x, y, ...].
+
+ def __init__(self, xy):
+ pass
+
+ ##
+ # Compacts the path, by removing points that are close to each
+ # other. This method modifies the path in place.
+
+ def compact(self, distance=2):
+ pass
+
+ ##
+ # Gets the bounding box.
+
+ def getbbox(self):
+ pass
+
+ ##
+ # Maps the path through a function.
+
+ def map(self, function):
+ pass
+
+ ##
+ # Converts the path to Python list.
+ #
+ # @param flat By default, this function returns a list of 2-tuples
+ # [(x, y), ...]. If this argument is true, it returns a flat
+ # list [x, y, ...] instead.
+ # @return A list of coordinates.
+
+ def tolist(self, flat=0):
+ pass
+
+ ##
+ # Transforms the path.
+
+ def transform(self, matrix):
+ pass
+
+
+# override with C implementation
+Path = Image.core.path
diff --git a/Imaging/PIL/ImageQt.py b/Imaging/PIL/ImageQt.py
new file mode 100644
index 0000000..2e9f476
--- /dev/null
+++ b/Imaging/PIL/ImageQt.py
@@ -0,0 +1,84 @@
+#
+# The Python Imaging Library.
+# $Id: ImageQt.py 2741 2006-06-18 16:17:20Z fredrik $
+#
+# a simple Qt image interface.
+#
+# history:
+# 2006-06-03 fl: created
+# 2006-06-04 fl: inherit from QImage instead of wrapping it
+# 2006-06-05 fl: removed toimage helper; move string support to ImageQt
+#
+# Copyright (c) 2006 by Secret Labs AB
+# Copyright (c) 2006 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image
+
+from PyQt4.QtGui import QImage, qRgb
+
+##
+# (Internal) Turns an RGB color into a Qt compatible color integer.
+
+def rgb(r, g, b):
+ # use qRgb to pack the colors, and then turn the resulting long
+ # into a negative integer with the same bitpattern.
+ return (qRgb(r, g, b) & 0xffffff) - 0x1000000
+
+##
+# An PIL image wrapper for Qt. This is a subclass of PyQt4's QImage
+# class.
+#
+# @param im A PIL Image object, or a file name (given either as Python
+# string or a PyQt string object).
+
+class ImageQt(QImage):
+
+ def __init__(self, im):
+
+ data = None
+ colortable = None
+
+ # handle filename, if given instead of image name
+ if hasattr(im, "toUtf8"):
+ # FIXME - is this really the best way to do this?
+ im = unicode(im.toUtf8(), "utf-8")
+ if Image.isStringType(im):
+ im = Image.open(im)
+
+ if im.mode == "1":
+ format = QImage.Format_Mono
+ elif im.mode == "L":
+ format = QImage.Format_Indexed8
+ colortable = []
+ for i in range(256):
+ colortable.append(rgb(i, i, i))
+ elif im.mode == "P":
+ format = QImage.Format_Indexed8
+ colortable = []
+ palette = im.getpalette()
+ for i in range(0, len(palette), 3):
+ colortable.append(rgb(*palette[i:i+3]))
+ elif im.mode == "RGB":
+ data = im.tostring("raw", "BGRX")
+ format = QImage.Format_RGB32
+ elif im.mode == "RGBA":
+ try:
+ data = im.tostring("raw", "BGRA")
+ except SystemError:
+ # workaround for earlier versions
+ r, g, b, a = im.split()
+ im = Image.merge("RGBA", (b, g, r, a))
+ format = QImage.Format_ARGB32
+ else:
+ raise ValueError("unsupported image mode %r" % im.mode)
+
+ # must keep a reference, or Qt will crash!
+ self.__data = data or im.tostring()
+
+ QImage.__init__(self, self.__data, im.size[0], im.size[1], format)
+
+ if colortable:
+ self.setColorTable(colortable)
diff --git a/Imaging/PIL/ImageSequence.py b/Imaging/PIL/ImageSequence.py
new file mode 100644
index 0000000..452b096
--- /dev/null
+++ b/Imaging/PIL/ImageSequence.py
@@ -0,0 +1,38 @@
+#
+# The Python Imaging Library.
+# $Id: ImageSequence.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# sequence support classes
+#
+# history:
+# 1997-02-20 fl Created
+#
+# Copyright (c) 1997 by Secret Labs AB.
+# Copyright (c) 1997 by Fredrik Lundh.
+#
+# See the README file for information on usage and redistribution.
+#
+
+##
+# This class implements an iterator object that can be used to loop
+# over an image sequence.
+
+class Iterator:
+
+ ##
+ # Create an iterator.
+ #
+ # @param im An image object.
+
+ def __init__(self, im):
+ if not hasattr(im, "seek"):
+ raise AttributeError("im must have seek method")
+ self.im = im
+
+ def __getitem__(self, ix):
+ try:
+ if ix:
+ self.im.seek(ix)
+ return self.im
+ except EOFError:
+ raise IndexError # end of sequence
diff --git a/Imaging/PIL/ImageStat.py b/Imaging/PIL/ImageStat.py
new file mode 100644
index 0000000..d53e645
--- /dev/null
+++ b/Imaging/PIL/ImageStat.py
@@ -0,0 +1,179 @@
+#
+# The Python Imaging Library.
+# $Id: ImageStat.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# global image statistics
+#
+# History:
+# 1996-04-05 fl Created
+# 1997-05-21 fl Added mask; added rms, var, stddev attributes
+# 1997-08-05 fl Added median
+# 1998-07-05 hk Fixed integer overflow error
+#
+# Notes:
+# This class shows how to implement delayed evaluation of attributes.
+# To get a certain value, simply access the corresponding attribute.
+# The __getattr__ dispatcher takes care of the rest.
+#
+# Copyright (c) Secret Labs AB 1997.
+# Copyright (c) Fredrik Lundh 1996-97.
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image
+import operator, math
+
+##
+# The <b>ImageStat</b> module calculates global statistics for an
+# image, or a region of an image.
+##
+
+##
+# Calculate statistics for the given image. If a mask is included,
+# only the regions covered by that mask are included in the
+# statistics.
+
+class Stat:
+ "Get image or feature statistics"
+
+ ##
+ # Create a statistics object.
+ #
+ # @def __init__(image, mask=None)
+ # @param image A PIL image, or a precalculate histogram.
+ # @param mask An optional mask.
+
+ def __init__(self, image_or_list, mask = None):
+ try:
+ if mask:
+ self.h = image_or_list.histogram(mask)
+ else:
+ self.h = image_or_list.histogram()
+ except AttributeError:
+ self.h = image_or_list # assume it to be a histogram list
+ if type(self.h) != type([]):
+ raise TypeError, "first argument must be image or list"
+ self.bands = range(len(self.h) / 256)
+
+ def __getattr__(self, id):
+ "Calculate missing attribute"
+ if id[:4] == "_get":
+ raise AttributeError, id
+ # calculate missing attribute
+ v = getattr(self, "_get" + id)()
+ setattr(self, id, v)
+ return v
+
+ def _getextrema(self):
+ "Get min/max values for each band in the image"
+
+ def minmax(histogram):
+ n = 255
+ x = 0
+ for i in range(256):
+ if histogram[i]:
+ n = min(n, i)
+ x = max(x, i)
+ return n, x # returns (255, 0) if there's no data in the histogram
+
+ v = []
+ for i in range(0, len(self.h), 256):
+ v.append(minmax(self.h[i:]))
+ return v
+
+ def _getcount(self):
+ "Get total number of pixels in each layer"
+
+ v = []
+ for i in range(0, len(self.h), 256):
+ v.append(reduce(operator.add, self.h[i:i+256]))
+ return v
+
+ def _getsum(self):
+ "Get sum of all pixels in each layer"
+
+ v = []
+ for i in range(0, len(self.h), 256):
+ sum = 0.0
+ for j in range(256):
+ sum = sum + j * self.h[i+j]
+ v.append(sum)
+ return v
+
+ def _getsum2(self):
+ "Get squared sum of all pixels in each layer"
+
+ v = []
+ for i in range(0, len(self.h), 256):
+ sum2 = 0.0
+ for j in range(256):
+ sum2 = sum2 + (j ** 2) * float(self.h[i+j])
+ v.append(sum2)
+ return v
+
+ def _getmean(self):
+ "Get average pixel level for each layer"
+
+ v = []
+ for i in self.bands:
+ v.append(self.sum[i] / self.count[i])
+ return v
+
+ def _getmedian(self):
+ "Get median pixel level for each layer"
+
+ v = []
+ for i in self.bands:
+ s = 0
+ l = self.count[i]/2
+ b = i * 256
+ for j in range(256):
+ s = s + self.h[b+j]
+ if s > l:
+ break
+ v.append(j)
+ return v
+
+ def _getrms(self):
+ "Get RMS for each layer"
+
+ v = []
+ for i in self.bands:
+ v.append(math.sqrt(self.sum2[i] / self.count[i]))
+ return v
+
+
+ def _getvar(self):
+ "Get variance for each layer"
+
+ v = []
+ for i in self.bands:
+ n = self.count[i]
+ v.append((self.sum2[i]-(self.sum[i]**2.0)/n)/n)
+ return v
+
+ def _getstddev(self):
+ "Get standard deviation for each layer"
+
+ v = []
+ for i in self.bands:
+ v.append(math.sqrt(self.var[i]))
+ return v
+
+Global = Stat # compatibility
+
+if __name__ == "__main__":
+
+ im = Image.open("Images/lena.ppm")
+
+ st = Stat(im)
+
+ print "extrema", st.extrema
+ print "sum ", st.sum
+ print "mean ", st.mean
+ print "median ", st.median
+ print "rms ", st.rms
+ print "sum2 ", st.sum2
+ print "var ", st.var
+ print "stddev ", st.stddev
diff --git a/Imaging/PIL/ImageTk.py b/Imaging/PIL/ImageTk.py
new file mode 100644
index 0000000..30f7c0e
--- /dev/null
+++ b/Imaging/PIL/ImageTk.py
@@ -0,0 +1,296 @@
+#
+# The Python Imaging Library.
+# $Id: ImageTk.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# a Tk display interface
+#
+# History:
+# 96-04-08 fl Created
+# 96-09-06 fl Added getimage method
+# 96-11-01 fl Rewritten, removed image attribute and crop method
+# 97-05-09 fl Use PyImagingPaste method instead of image type
+# 97-05-12 fl Minor tweaks to match the IFUNC95 interface
+# 97-05-17 fl Support the "pilbitmap" booster patch
+# 97-06-05 fl Added file= and data= argument to image constructors
+# 98-03-09 fl Added width and height methods to Image classes
+# 98-07-02 fl Use default mode for "P" images without palette attribute
+# 98-07-02 fl Explicitly destroy Tkinter image objects
+# 99-07-24 fl Support multiple Tk interpreters (from Greg Couch)
+# 99-07-26 fl Automatically hook into Tkinter (if possible)
+# 99-08-15 fl Hook uses _imagingtk instead of _imaging
+#
+# Copyright (c) 1997-1999 by Secret Labs AB
+# Copyright (c) 1996-1997 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Tkinter, Image
+
+##
+# The <b>ImageTk</b> module contains support to create and modify
+# Tkinter <b>BitmapImage</b> and <b>PhotoImage</b> objects.
+# <p>
+# For examples, see the demo programs in the <i>Scripts</i>
+# directory.
+##
+
+# --------------------------------------------------------------------
+# Check for Tkinter interface hooks
+
+_pilbitmap_ok = None
+
+def _pilbitmap_check():
+ global _pilbitmap_ok
+ if _pilbitmap_ok is None:
+ try:
+ im = Image.new("1", (1,1))
+ Tkinter.BitmapImage(data="PIL:%d" % im.im.id)
+ _pilbitmap_ok = 1
+ except Tkinter.TclError:
+ _pilbitmap_ok = 0
+ return _pilbitmap_ok
+
+# --------------------------------------------------------------------
+# PhotoImage
+
+##
+# Creates a Tkinter-compatible photo image. This can be used
+# everywhere Tkinter expects an image object. If the image is an RGBA
+# image, pixels having alpha 0 are treated as transparent.
+
+class PhotoImage:
+
+ ##
+ # Create a photo image object. The constructor takes either
+ # a PIL image, or a mode and a size. Alternatively, you can
+ # use the <b>file</b> or <b>data</b> options to initialize
+ # the photo image object.
+ # <p>
+ # @def __init__(image=None, size=None, **options)
+ # @param image Either a PIL image, or a mode string. If a
+ # mode string is used, a size must also be given.
+ # @param size If the first argument is a mode string, this
+ # defines the size of the image.
+ # @keyparam file A filename to load the image from (using
+ # Image.open(file)).
+ # @keyparam data An 8-bit string containing image data (as
+ # loaded from an image file).
+
+ def __init__(self, image=None, size=None, **kw):
+
+ # Tk compatibility: file or data
+ if image is None:
+ if kw.has_key("file"):
+ image = Image.open(kw["file"])
+ del kw["file"]
+ elif kw.has_key("data"):
+ from StringIO import StringIO
+ image = Image.open(StringIO(kw["data"]))
+ del kw["data"]
+
+ if hasattr(image, "mode") and hasattr(image, "size"):
+ # got an image instead of a mode
+ mode = image.mode
+ if mode == "P":
+ # palette mapped data
+ image.load()
+ try:
+ mode = image.palette.mode
+ except AttributeError:
+ mode = "RGB" # default
+ size = image.size
+ kw["width"], kw["height"] = size
+ else:
+ mode = image
+ image = None
+
+ if mode not in ["1", "L", "RGB", "RGBA"]:
+ mode = Image.getmodebase(mode)
+
+ self.__mode = mode
+ self.__size = size
+ self.__photo = apply(Tkinter.PhotoImage, (), kw)
+ self.tk = self.__photo.tk
+ if image:
+ self.paste(image)
+
+ def __del__(self):
+ name = self.__photo.name
+ self.__photo.name = None
+ try:
+ self.__photo.tk.call("image", "delete", name)
+ except:
+ pass # ignore internal errors
+
+ ##
+ # Get the Tkinter photo image identifier. This method is
+ # automatically called by Tkinter whenever a PhotoImage object is
+ # passed to a Tkinter method.
+ #
+ # @return A Tkinter photo image identifier (a string).
+
+ def __str__(self):
+ return str(self.__photo)
+
+ ##
+ # Get the width of the image.
+ #
+ # @return The width, in pixels.
+
+ def width(self):
+ return self.__size[0]
+
+ ##
+ # Get the height of the image.
+ #
+ # @return The height, in pixels.
+
+ def height(self):
+ return self.__size[1]
+
+ ##
+ # Paste a PIL image into the photo image. Note that this can
+ # be very slow if the photo image is displayed.
+ #
+ # @param im A PIL image. The size must match the target region.
+ # If the mode does not match, the image is converted to the
+ # mode of the bitmap image.
+ # @param box A 4-tuple defining the left, upper, right, and
+ # lower pixel coordinate. If None is given instead of a
+ # tuple, all of the image is assumed.
+
+ def paste(self, im, box=None):
+
+ # convert to blittable
+ im.load()
+ image = im.im
+ if image.isblock() and im.mode == self.__mode:
+ block = image
+ else:
+ block = image.new_block(self.__mode, im.size)
+ image.convert2(block, image) # convert directly between buffers
+
+ tk = self.__photo.tk
+
+ try:
+ tk.call("PyImagingPhoto", self.__photo, block.id)
+ except Tkinter.TclError, v:
+ # activate Tkinter hook
+ try:
+ import _imagingtk
+ try:
+ _imagingtk.tkinit(tk.interpaddr(), 1)
+ except AttributeError:
+ _imagingtk.tkinit(id(tk), 0)
+ tk.call("PyImagingPhoto", self.__photo, block.id)
+ except (ImportError, AttributeError, Tkinter.TclError):
+ raise # configuration problem; cannot attach to Tkinter
+
+# --------------------------------------------------------------------
+# BitmapImage
+
+##
+# Create a Tkinter-compatible bitmap image. This can be used
+# everywhere Tkinter expects an image object.
+
+class BitmapImage:
+
+ ##
+ # Create a Tkinter-compatible bitmap image.
+ # <p>
+ # The given image must have mode "1". Pixels having value 0 are
+ # treated as transparent. Options, if any, are passed on to
+ # Tkinter. The most commonly used option is <b>foreground</b>,
+ # which is used to specify the colour for the non-transparent
+ # parts. See the Tkinter documentation for information on how to
+ # specify colours.
+ #
+ # @def __init__(image=None, **options)
+ # @param image A PIL image.
+
+ def __init__(self, image=None, **kw):
+
+ # Tk compatibility: file or data
+ if image is None:
+ if kw.has_key("file"):
+ image = Image.open(kw["file"])
+ del kw["file"]
+ elif kw.has_key("data"):
+ from StringIO import StringIO
+ image = Image.open(StringIO(kw["data"]))
+ del kw["data"]
+
+ self.__mode = image.mode
+ self.__size = image.size
+
+ if _pilbitmap_check():
+ # fast way (requires the pilbitmap booster patch)
+ image.load()
+ kw["data"] = "PIL:%d" % image.im.id
+ self.__im = image # must keep a reference
+ else:
+ # slow but safe way
+ kw["data"] = image.tobitmap()
+ self.__photo = apply(Tkinter.BitmapImage, (), kw)
+
+ def __del__(self):
+ name = self.__photo.name
+ self.__photo.name = None
+ try:
+ self.__photo.tk.call("image", "delete", name)
+ except:
+ pass # ignore internal errors
+
+ ##
+ # Get the width of the image.
+ #
+ # @return The width, in pixels.
+
+ def width(self):
+ return self.__size[0]
+
+ ##
+ # Get the height of the image.
+ #
+ # @return The height, in pixels.
+
+ def height(self):
+ return self.__size[1]
+
+ ##
+ # Get the Tkinter bitmap image identifier. This method is
+ # automatically called by Tkinter whenever a BitmapImage object
+ # is passed to a Tkinter method.
+ #
+ # @return A Tkinter bitmap image identifier (a string).
+
+ def __str__(self):
+ return str(self.__photo)
+
+##
+# Copies the contents of a PhotoImage to a PIL image memory.
+
+def getimage(photo):
+ photo.tk.call("PyImagingPhotoGet", photo)
+
+# --------------------------------------------------------------------
+# Helper for the Image.show method.
+
+def _show(image, title):
+
+ class UI(Tkinter.Label):
+ def __init__(self, master, im):
+ if im.mode == "1":
+ self.image = BitmapImage(im, foreground="white", master=master)
+ else:
+ self.image = PhotoImage(im, master=master)
+ Tkinter.Label.__init__(self, master, image=self.image,
+ bg="black", bd=0)
+
+ if not Tkinter._default_root:
+ raise IOError, "tkinter not initialized"
+ top = Tkinter.Toplevel()
+ if title:
+ top.title(title)
+ UI(top, image).pack()
diff --git a/Imaging/PIL/ImageTransform.py b/Imaging/PIL/ImageTransform.py
new file mode 100644
index 0000000..2944cd3
--- /dev/null
+++ b/Imaging/PIL/ImageTransform.py
@@ -0,0 +1,91 @@
+#
+# The Python Imaging Library.
+# $Id: ImageTransform.py 2813 2006-10-07 10:11:35Z fredrik $
+#
+# transform wrappers
+#
+# History:
+# 2002-04-08 fl Created
+#
+# Copyright (c) 2002 by Secret Labs AB
+# Copyright (c) 2002 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image
+
+class Transform:
+ def __init__(self, data):
+ self.data = data
+ def getdata(self):
+ return self.method, self.data
+
+##
+# Define an affine image transform.
+# <p>
+# This function takes a 6-tuple (<i>a, b, c, d, e, f</i>) which
+# contain the first two rows from an affine transform matrix. For
+# each pixel (<i>x, y</i>) in the output image, the new value is
+# taken from a position (a <i>x</i> + b <i>y</i> + c,
+# d <i>x</i> + e <i>y</i> + f) in the input image, rounded to
+# nearest pixel.
+# <p>
+# This function can be used to scale, translate, rotate, and shear the
+# original image.
+#
+# @def AffineTransform(matrix)
+# @param matrix A 6-tuple (<i>a, b, c, d, e, f</i>) containing
+# the first two rows from an affine transform matrix.
+# @see Image#Image.transform
+
+class AffineTransform(Transform):
+ method = Image.AFFINE
+
+##
+# Define a transform to extract a subregion from an image.
+# <p>
+# Maps a rectangle (defined by two corners) from the image to a
+# rectangle of the given size. The resulting image will contain
+# data sampled from between the corners, such that (<i>x0, y0</i>)
+# in the input image will end up at (0,0) in the output image,
+# and (<i>x1, y1</i>) at <i>size</i>.
+# <p>
+# This method can be used to crop, stretch, shrink, or mirror an
+# arbitrary rectangle in the current image. It is slightly slower than
+# <b>crop</b>, but about as fast as a corresponding <b>resize</b>
+# operation.
+#
+# @def ExtentTransform(bbox)
+# @param bbox A 4-tuple (<i>x0, y0, x1, y1</i>) which specifies
+# two points in the input image's coordinate system.
+# @see Image#Image.transform
+
+class ExtentTransform(Transform):
+ method = Image.EXTENT
+
+##
+# Define an quad image transform.
+# <p>
+# Maps a quadrilateral (a region defined by four corners) from the
+# image to a rectangle of the given size.
+#
+# @def QuadTransform(xy)
+# @param xy An 8-tuple (<i>x0, y0, x1, y1, x2, y2, y3, y3</i>) which
+# contain the upper left, lower left, lower right, and upper right
+# corner of the source quadrilateral.
+# @see Image#Image.transform
+
+class QuadTransform(Transform):
+ method = Image.QUAD
+
+##
+# Define an mesh image transform. A mesh transform consists of one
+# or more individual quad transforms.
+#
+# @def MeshTransform(data)
+# @param data A list of (bbox, quad) tuples.
+# @see Image#Image.transform
+
+class MeshTransform(Transform):
+ method = Image.MESH
diff --git a/Imaging/PIL/ImageWin.py b/Imaging/PIL/ImageWin.py
new file mode 100644
index 0000000..13c56b9
--- /dev/null
+++ b/Imaging/PIL/ImageWin.py
@@ -0,0 +1,215 @@
+#
+# The Python Imaging Library.
+# $Id: ImageWin.py 2662 2006-03-21 22:41:02Z fredrik $
+#
+# a Windows DIB display interface
+#
+# History:
+# 1996-05-20 fl Created
+# 1996-09-20 fl Fixed subregion exposure
+# 1997-09-21 fl Added draw primitive (for tzPrint)
+# 2003-05-21 fl Added experimental Window/ImageWindow classes
+# 2003-09-05 fl Added fromstring/tostring methods
+#
+# Copyright (c) Secret Labs AB 1997-2003.
+# Copyright (c) Fredrik Lundh 1996-2003.
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image
+
+##
+# The <b>ImageWin</b> module contains support to create and display
+# images under Windows 95/98, NT, 2000 and later.
+
+class HDC:
+ def __init__(self, dc):
+ self.dc = dc
+ def __int__(self):
+ return self.dc
+
+class HWND:
+ def __init__(self, wnd):
+ self.wnd = wnd
+ def __int__(self):
+ return self.wnd
+
+##
+# Create a Windows bitmap with the given mode and size. The mode can
+# be one of "1", "L", "P", or "RGB".
+#
+# If the display requires a palette, this constructor creates a
+# suitable palette and associates it with the image. For an "L" image,
+# 128 greylevels are allocated. For an "RGB" image, a 6x6x6 colour
+# cube is used, together with 20 greylevels.
+#
+# To make sure that palettes work properly under Windows, you must
+# call the <b>palette</b> method upon certain events from Windows.
+
+class Dib:
+
+ ##
+ # Create Windows bitmap.
+ #
+ # @param image Either a PIL image, or a mode string. If a
+ # mode string is used, a size must also be given. The
+ # mode can be one of "1", "L", "P", or "RGB".
+ # @param size If the first argument is a mode string, this
+ # defines the size of the image.
+
+ def __init__(self, image, size=None):
+ if hasattr(image, "mode") and hasattr(image, "size"):
+ mode = image.mode
+ size = image.size
+ else:
+ mode = image
+ image = None
+ if mode not in ["1", "L", "P", "RGB"]:
+ mode = Image.getmodebase(mode)
+ self.image = Image.core.display(mode, size)
+ self.mode = mode
+ self.size = size
+ if image:
+ self.paste(image)
+
+ ##
+ # Copy the bitmap contents to a device context.
+ #
+ # @param handle Device context (HDC), cast to a Python integer,
+ # or a HDC or HWND instance. In PythonWin, you can use the
+ # <b>GetHandleAttrib</b> method of the <b>CDC</b> class to get
+ # a suitable handle.
+
+ def expose(self, handle):
+ if isinstance(handle, HWND):
+ dc = self.image.getdc(handle)
+ try:
+ result = self.image.expose(dc)
+ finally:
+ self.image.releasedc(handle, dc)
+ else:
+ result = self.image.expose(handle)
+ return result
+
+ def draw(self, handle, dst, src=None):
+ if not src:
+ src = (0,0) + self.size
+ if isinstance(handle, HWND):
+ dc = self.image.getdc(handle)
+ try:
+ result = self.image.draw(dc, dst, src)
+ finally:
+ self.image.releasedc(handle, dc)
+ else:
+ result = self.image.draw(handle, dst, src)
+ return result
+
+ ##
+ # Installs the palette associated with the image in the
+ # given device context.
+ # <p>
+ # This method should be called upon <b>QUERYNEWPALETTE</b>
+ # and <b>PALETTECHANGED</b> events from Windows. If this
+ # method returns a non-zero value, one or more display
+ # palette entries were changed, and the image should be
+ # redrawn.
+ #
+ # @param handle Device context (HDC), cast to a Python integer,
+ # or an HDC or HWND instance.
+ # @return A true value if one or more entries were changed
+ # (this indicates that the image should be redrawn).
+
+ def query_palette(self, handle):
+ if isinstance(handle, HWND):
+ handle = self.image.getdc(handle)
+ try:
+ result = self.image.query_palette(handle)
+ finally:
+ self.image.releasedc(handle, handle)
+ else:
+ result = self.image.query_palette(handle)
+ return result
+
+ ##
+ # Paste a PIL image into the bitmap image.
+ #
+ # @param im A PIL image. The size must match the target region.
+ # If the mode does not match, the image is converted to the
+ # mode of the bitmap image.
+ # @param box A 4-tuple defining the left, upper, right, and
+ # lower pixel coordinate. If None is given instead of a
+ # tuple, all of the image is assumed.
+
+ def paste(self, im, box=None):
+ im.load()
+ if self.mode != im.mode:
+ im = im.convert(self.mode)
+ if box:
+ self.image.paste(im.im, box)
+ else:
+ self.image.paste(im.im)
+
+ ##
+ # Load display memory contents from string buffer.
+ #
+ # @param buffer A string buffer containing display data (usually
+ # data returned from <b>tostring</b>)
+
+ def fromstring(self, buffer):
+ return self.image.fromstring(buffer)
+
+ ##
+ # Copy display memory contents to string buffer.
+ #
+ # @return A string buffer containing display data.
+
+ def tostring(self):
+ return self.image.tostring()
+
+
+##
+# Create a Window with the given title size.
+
+class Window:
+
+ def __init__(self, title="PIL", width=None, height=None):
+ self.hwnd = Image.core.createwindow(
+ title, self.__dispatcher, width or 0, height or 0
+ )
+
+ def __dispatcher(self, action, *args):
+ return apply(getattr(self, "ui_handle_" + action), args)
+
+ def ui_handle_clear(self, dc, x0, y0, x1, y1):
+ pass
+
+ def ui_handle_damage(self, x0, y0, x1, y1):
+ pass
+
+ def ui_handle_destroy(self):
+ pass
+
+ def ui_handle_repair(self, dc, x0, y0, x1, y1):
+ pass
+
+ def ui_handle_resize(self, width, height):
+ pass
+
+ def mainloop(self):
+ Image.core.eventloop()
+
+##
+# Create an image window which displays the given image.
+
+class ImageWindow(Window):
+
+ def __init__(self, image, title="PIL"):
+ if not isinstance(image, Dib):
+ image = Dib(image)
+ self.image = image
+ width, height = image.size
+ Window.__init__(self, title, width=width, height=height)
+
+ def ui_handle_repair(self, dc, x0, y0, x1, y1):
+ self.image.draw(dc, (x0, y0, x1, y1))
diff --git a/Imaging/PIL/ImtImagePlugin.py b/Imaging/PIL/ImtImagePlugin.py
new file mode 100644
index 0000000..f321ae3
--- /dev/null
+++ b/Imaging/PIL/ImtImagePlugin.py
@@ -0,0 +1,93 @@
+#
+# The Python Imaging Library.
+# $Id: ImtImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# IM Tools support for PIL
+#
+# history:
+# 1996-05-27 fl Created (read 8-bit images only)
+# 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.2)
+#
+# Copyright (c) Secret Labs AB 1997-2001.
+# Copyright (c) Fredrik Lundh 1996-2001.
+#
+# See the README file for information on usage and redistribution.
+#
+
+
+__version__ = "0.2"
+
+import string, re
+
+import Image, ImageFile
+
+#
+# --------------------------------------------------------------------
+
+field = re.compile(r"([a-z]*) ([^ \r\n]*)")
+
+##
+# Image plugin for IM Tools images.
+
+class ImtImageFile(ImageFile.ImageFile):
+
+ format = "IMT"
+ format_description = "IM Tools"
+
+ def _open(self):
+
+ # Quick rejection: if there's not a LF among the first
+ # 100 bytes, this is (probably) not a text header.
+
+ if not "\n" in self.fp.read(100):
+ raise SyntaxError, "not an IM file"
+ self.fp.seek(0)
+
+ xsize = ysize = 0
+
+ while 1:
+
+ s = self.fp.read(1)
+ if not s:
+ break
+
+ if s == chr(12):
+
+ # image data begins
+ self.tile = [("raw", (0,0)+self.size,
+ self.fp.tell(),
+ (self.mode, 0, 1))]
+
+ break
+
+ else:
+
+ # read key/value pair
+ # FIXME: dangerous, may read whole file
+ s = s + self.fp.readline()
+ if len(s) == 1 or len(s) > 100:
+ break
+ if s[0] == "*":
+ continue # comment
+
+ m = field.match(s)
+ if not m:
+ break
+ k, v = m.group(1,2)
+ if k == "width":
+ xsize = int(v)
+ self.size = xsize, ysize
+ elif k == "height":
+ ysize = int(v)
+ self.size = xsize, ysize
+ elif k == "pixel" and v == "n8":
+ self.mode = "L"
+
+
+#
+# --------------------------------------------------------------------
+
+Image.register_open("IMT", ImtImageFile)
+
+#
+# no extension registered (".im" is simply too common)
diff --git a/Imaging/PIL/IptcImagePlugin.py b/Imaging/PIL/IptcImagePlugin.py
new file mode 100644
index 0000000..3535759
--- /dev/null
+++ b/Imaging/PIL/IptcImagePlugin.py
@@ -0,0 +1,280 @@
+#
+# The Python Imaging Library.
+# $Id: IptcImagePlugin.py 2813 2006-10-07 10:11:35Z fredrik $
+#
+# IPTC/NAA file handling
+#
+# history:
+# 1995-10-01 fl Created
+# 1998-03-09 fl Cleaned up and added to PIL
+# 2002-06-18 fl Added getiptcinfo helper
+#
+# Copyright (c) Secret Labs AB 1997-2002.
+# Copyright (c) Fredrik Lundh 1995.
+#
+# See the README file for information on usage and redistribution.
+#
+
+
+__version__ = "0.3"
+
+
+import Image, ImageFile
+import os, tempfile
+
+
+COMPRESSION = {
+ 1: "raw",
+ 5: "jpeg"
+}
+
+PAD = chr(0) * 4
+
+#
+# Helpers
+
+def i16(c):
+ return ord(c[1]) + (ord(c[0])<<8)
+
+def i32(c):
+ return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
+
+def i(c):
+ return i32((PAD + c)[-4:])
+
+def dump(c):
+ for i in c:
+ print "%02x" % ord(i),
+ print
+
+##
+# Image plugin for IPTC/NAA datastreams. To read IPTC/NAA fields
+# from TIFF and JPEG files, use the <b>getiptcinfo</b> function.
+
+class IptcImageFile(ImageFile.ImageFile):
+
+ format = "IPTC"
+ format_description = "IPTC/NAA"
+
+ def getint(self, key):
+ return i(self.info[key])
+
+ def field(self):
+ #
+ # get a IPTC field header
+ s = self.fp.read(5)
+ if not len(s):
+ return None, 0
+
+ tag = ord(s[1]), ord(s[2])
+
+ # syntax
+ if ord(s[0]) != 0x1C or tag[0] < 1 or tag[0] > 9:
+ raise SyntaxError, "invalid IPTC/NAA file"
+
+ # field size
+ size = ord(s[3])
+ if size > 132:
+ raise IOError, "illegal field length in IPTC/NAA file"
+ elif size == 128:
+ size = 0
+ elif size > 128:
+ size = i(self.fp.read(size-128))
+ else:
+ size = i16(s[3:])
+
+ return tag, size
+
+ def _is_raw(self, offset, size):
+ #
+ # check if the file can be mapped
+
+ # DISABLED: the following only slows things down...
+ return 0
+
+ self.fp.seek(offset)
+ t, sz = self.field()
+ if sz != size[0]:
+ return 0
+ y = 1
+ while 1:
+ self.fp.seek(sz, 1)
+ t, s = self.field()
+ if t != (8, 10):
+ break
+ if s != sz:
+ return 0
+ y = y + 1
+ return y == size[1]
+
+ def _open(self):
+
+ # load descriptive fields
+ while 1:
+ offset = self.fp.tell()
+ tag, size = self.field()
+ if not tag or tag == (8,10):
+ break
+ if size:
+ self.info[tag] = self.fp.read(size)
+ else:
+ self.info[tag] = None
+ # print tag, self.info[tag]
+
+ # mode
+ layers = ord(self.info[(3,60)][0])
+ component = ord(self.info[(3,60)][1])
+ if self.info.has_key((3,65)):
+ id = ord(self.info[(3,65)][0])-1
+ else:
+ id = 0
+ if layers == 1 and not component:
+ self.mode = "L"
+ elif layers == 3 and component:
+ self.mode = "RGB"[id]
+ elif layers == 4 and component:
+ self.mode = "CMYK"[id]
+
+ # size
+ self.size = self.getint((3,20)), self.getint((3,30))
+
+ # compression
+ try:
+ compression = COMPRESSION[self.getint((3,120))]
+ except KeyError:
+ raise IOError, "Unknown IPTC image compression"
+
+ # tile
+ if tag == (8,10):
+ if compression == "raw" and self._is_raw(offset, self.size):
+ self.tile = [(compression, (offset, size + 5, -1),
+ (0, 0, self.size[0], self.size[1]))]
+ else:
+ self.tile = [("iptc", (compression, offset),
+ (0, 0, self.size[0], self.size[1]))]
+
+ def load(self):
+
+ if len(self.tile) != 1 or self.tile[0][0] != "iptc":
+ return ImageFile.ImageFile.load(self)
+
+ type, tile, box = self.tile[0]
+
+ encoding, offset = tile
+
+ self.fp.seek(offset)
+
+ # Copy image data to temporary file
+ outfile = tempfile.mktemp()
+ o = open(outfile, "wb")
+ if encoding == "raw":
+ # To simplify access to the extracted file,
+ # prepend a PPM header
+ o.write("P5\n%d %d\n255\n" % self.size)
+ while 1:
+ type, size = self.field()
+ if type != (8, 10):
+ break
+ while size > 0:
+ s = self.fp.read(min(size, 8192))
+ if not s:
+ break
+ o.write(s)
+ size = size - len(s)
+ o.close()
+
+ try:
+ try:
+ # fast
+ self.im = Image.core.open_ppm(outfile)
+ except:
+ # slightly slower
+ im = Image.open(outfile)
+ im.load()
+ self.im = im.im
+ finally:
+ try: os.unlink(outfile)
+ except: pass
+
+
+Image.register_open("IPTC", IptcImageFile)
+
+Image.register_extension("IPTC", ".iim")
+
+##
+# Get IPTC information from TIFF, JPEG, or IPTC file.
+#
+# @param im An image containing IPTC data.
+# @return A dictionary containing IPTC information, or None if
+# no IPTC information block was found.
+
+def getiptcinfo(im):
+
+ import TiffImagePlugin, JpegImagePlugin
+ import StringIO
+
+ data = None
+
+ if isinstance(im, IptcImageFile):
+ # return info dictionary right away
+ return im.info
+
+ elif isinstance(im, JpegImagePlugin.JpegImageFile):
+ # extract the IPTC/NAA resource
+ try:
+ app = im.app["APP13"]
+ if app[:14] == "Photoshop 3.0\x00":
+ app = app[14:]
+ # parse the image resource block
+ offset = 0
+ while app[offset:offset+4] == "8BIM":
+ offset = offset + 4
+ # resource code
+ code = JpegImagePlugin.i16(app, offset)
+ offset = offset + 2
+ # resource name (usually empty)
+ name_len = ord(app[offset])
+ name = app[offset+1:offset+1+name_len]
+ offset = 1 + offset + name_len
+ if offset & 1:
+ offset = offset + 1
+ # resource data block
+ size = JpegImagePlugin.i32(app, offset)
+ offset = offset + 4
+ if code == 0x0404:
+ # 0x0404 contains IPTC/NAA data
+ data = app[offset:offset+size]
+ break
+ offset = offset + size
+ if offset & 1:
+ offset = offset + 1
+ except (AttributeError, KeyError):
+ pass
+
+ elif isinstance(im, TiffImagePlugin.TiffImageFile):
+ # get raw data from the IPTC/NAA tag (PhotoShop tags the data
+ # as 4-byte integers, so we cannot use the get method...)
+ try:
+ type, data = im.tag.tagdata[TiffImagePlugin.IPTC_NAA_CHUNK]
+ except (AttributeError, KeyError):
+ pass
+
+ if data is None:
+ return None # no properties
+
+ # create an IptcImagePlugin object without initializing it
+ class FakeImage:
+ pass
+ im = FakeImage()
+ im.__class__ = IptcImageFile
+
+ # parse the IPTC information chunk
+ im.info = {}
+ im.fp = StringIO.StringIO(data)
+
+ try:
+ im._open()
+ except (IndexError, KeyError):
+ pass # expected failure
+
+ return im.info
diff --git a/Imaging/PIL/JpegImagePlugin.py b/Imaging/PIL/JpegImagePlugin.py
new file mode 100644
index 0000000..b8ba8e4
--- /dev/null
+++ b/Imaging/PIL/JpegImagePlugin.py
@@ -0,0 +1,430 @@
+#
+# The Python Imaging Library.
+# $Id: JpegImagePlugin.py 2763 2006-06-22 21:43:28Z fredrik $
+#
+# JPEG (JFIF) file handling
+#
+# See "Digital Compression and Coding of Continous-Tone Still Images,
+# Part 1, Requirements and Guidelines" (CCITT T.81 / ISO 10918-1)
+#
+# History:
+# 1995-09-09 fl Created
+# 1995-09-13 fl Added full parser
+# 1996-03-25 fl Added hack to use the IJG command line utilities
+# 1996-05-05 fl Workaround Photoshop 2.5 CMYK polarity bug
+# 1996-05-28 fl Added draft support, JFIF version (0.1)
+# 1996-12-30 fl Added encoder options, added progression property (0.2)
+# 1997-08-27 fl Save mode 1 images as BW (0.3)
+# 1998-07-12 fl Added YCbCr to draft and save methods (0.4)
+# 1998-10-19 fl Don't hang on files using 16-bit DQT's (0.4.1)
+# 2001-04-16 fl Extract DPI settings from JFIF files (0.4.2)
+# 2002-07-01 fl Skip pad bytes before markers; identify Exif files (0.4.3)
+# 2003-04-25 fl Added experimental EXIF decoder (0.5)
+# 2003-06-06 fl Added experimental EXIF GPSinfo decoder
+# 2003-09-13 fl Extract COM markers
+#
+# Copyright (c) 1997-2003 by Secret Labs AB.
+# Copyright (c) 1995-1996 by Fredrik Lundh.
+#
+# See the README file for information on usage and redistribution.
+#
+
+__version__ = "0.5"
+
+import array, string
+import Image, ImageFile
+
+def i16(c,o=0):
+ return ord(c[o+1]) + (ord(c[o])<<8)
+
+def i32(c,o=0):
+ return ord(c[o+3]) + (ord(c[o+2])<<8) + (ord(c[o+1])<<16) + (ord(c[o])<<24)
+
+#
+# Parser
+
+def Skip(self, marker):
+ n = i16(self.fp.read(2))-2
+ ImageFile._safe_read(self.fp, n)
+
+def APP(self, marker):
+ #
+ # Application marker. Store these in the APP dictionary.
+ # Also look for well-known application markers.
+
+ n = i16(self.fp.read(2))-2
+ s = ImageFile._safe_read(self.fp, n)
+
+ app = "APP%d" % (marker&15)
+
+ self.app[app] = s # compatibility
+ self.applist.append((app, s))
+
+ if marker == 0xFFE0 and s[:4] == "JFIF":
+ # extract JFIF information
+ self.info["jfif"] = version = i16(s, 5) # version
+ self.info["jfif_version"] = divmod(version, 256)
+ # extract JFIF properties
+ try:
+ jfif_unit = ord(s[7])
+ jfif_density = i16(s, 8), i16(s, 10)
+ except:
+ pass
+ else:
+ if jfif_unit == 1:
+ self.info["dpi"] = jfif_density
+ self.info["jfif_unit"] = jfif_unit
+ self.info["jfif_density"] = jfif_density
+ elif marker == 0xFFE1 and s[:5] == "Exif\0":
+ # extract Exif information (incomplete)
+ self.info["exif"] = s # FIXME: value will change
+ elif marker == 0xFFE2 and s[:5] == "FPXR\0":
+ # extract FlashPix information (incomplete)
+ self.info["flashpix"] = s # FIXME: value will change
+ elif marker == 0xFFEE and s[:5] == "Adobe":
+ self.info["adobe"] = i16(s, 5)
+ # extract Adobe custom properties
+ try:
+ adobe_transform = ord(s[1])
+ except:
+ pass
+ else:
+ self.info["adobe_transform"] = adobe_transform
+
+def COM(self, marker):
+ #
+ # Comment marker. Store these in the APP dictionary.
+
+ n = i16(self.fp.read(2))-2
+ s = ImageFile._safe_read(self.fp, n)
+
+ self.app["COM"] = s # compatibility
+ self.applist.append(("COM", s))
+
+def SOF(self, marker):
+ #
+ # Start of frame marker. Defines the size and mode of the
+ # image. JPEG is colour blind, so we use some simple
+ # heuristics to map the number of layers to an appropriate
+ # mode. Note that this could be made a bit brighter, by
+ # looking for JFIF and Adobe APP markers.
+
+ n = i16(self.fp.read(2))-2
+ s = ImageFile._safe_read(self.fp, n)
+ self.size = i16(s[3:]), i16(s[1:])
+
+ self.bits = ord(s[0])
+ if self.bits != 8:
+ raise SyntaxError("cannot handle %d-bit layers" % self.bits)
+
+ self.layers = ord(s[5])
+ if self.layers == 1:
+ self.mode = "L"
+ elif self.layers == 3:
+ self.mode = "RGB"
+ elif self.layers == 4:
+ self.mode = "CMYK"
+ else:
+ raise SyntaxError("cannot handle %d-layer images" % self.layers)
+
+ if marker in [0xFFC2, 0xFFC6, 0xFFCA, 0xFFCE]:
+ self.info["progression"] = 1
+
+ for i in range(6, len(s), 3):
+ t = s[i:i+3]
+ # 4-tuples: id, vsamp, hsamp, qtable
+ self.layer.append((t[0], ord(t[1])/16, ord(t[1])&15, ord(t[2])))
+
+def DQT(self, marker):
+ #
+ # Define quantization table. Support baseline 8-bit tables
+ # only. Note that there might be more than one table in
+ # each marker.
+
+ # FIXME: The quantization tables can be used to estimate the
+ # compression quality.
+
+ n = i16(self.fp.read(2))-2
+ s = ImageFile._safe_read(self.fp, n)
+ while len(s):
+ if len(s) < 65:
+ raise SyntaxError("bad quantization table marker")
+ v = ord(s[0])
+ if v/16 == 0:
+ self.quantization[v&15] = array.array("b", s[1:65])
+ s = s[65:]
+ else:
+ return # FIXME: add code to read 16-bit tables!
+ # raise SyntaxError, "bad quantization table element size"
+
+
+#
+# JPEG marker table
+
+MARKER = {
+ 0xFFC0: ("SOF0", "Baseline DCT", SOF),
+ 0xFFC1: ("SOF1", "Extended Sequential DCT", SOF),
+ 0xFFC2: ("SOF2", "Progressive DCT", SOF),
+ 0xFFC3: ("SOF3", "Spatial lossless", SOF),
+ 0xFFC4: ("DHT", "Define Huffman table", Skip),
+ 0xFFC5: ("SOF5", "Differential sequential DCT", SOF),
+ 0xFFC6: ("SOF6", "Differential progressive DCT", SOF),
+ 0xFFC7: ("SOF7", "Differential spatial", SOF),
+ 0xFFC8: ("JPG", "Extension", None),
+ 0xFFC9: ("SOF9", "Extended sequential DCT (AC)", SOF),
+ 0xFFCA: ("SOF10", "Progressive DCT (AC)", SOF),
+ 0xFFCB: ("SOF11", "Spatial lossless DCT (AC)", SOF),
+ 0xFFCC: ("DAC", "Define arithmetic coding conditioning", Skip),
+ 0xFFCD: ("SOF13", "Differential sequential DCT (AC)", SOF),
+ 0xFFCE: ("SOF14", "Differential progressive DCT (AC)", SOF),
+ 0xFFCF: ("SOF15", "Differential spatial (AC)", SOF),
+ 0xFFD0: ("RST0", "Restart 0", None),
+ 0xFFD1: ("RST1", "Restart 1", None),
+ 0xFFD2: ("RST2", "Restart 2", None),
+ 0xFFD3: ("RST3", "Restart 3", None),
+ 0xFFD4: ("RST4", "Restart 4", None),
+ 0xFFD5: ("RST5", "Restart 5", None),
+ 0xFFD6: ("RST6", "Restart 6", None),
+ 0xFFD7: ("RST7", "Restart 7", None),
+ 0xFFD8: ("SOI", "Start of image", None),
+ 0xFFD9: ("EOI", "End of image", None),
+ 0xFFDA: ("SOS", "Start of scan", Skip),
+ 0xFFDB: ("DQT", "Define quantization table", DQT),
+ 0xFFDC: ("DNL", "Define number of lines", Skip),
+ 0xFFDD: ("DRI", "Define restart interval", Skip),
+ 0xFFDE: ("DHP", "Define hierarchical progression", SOF),
+ 0xFFDF: ("EXP", "Expand reference component", Skip),
+ 0xFFE0: ("APP0", "Application segment 0", APP),
+ 0xFFE1: ("APP1", "Application segment 1", APP),
+ 0xFFE2: ("APP2", "Application segment 2", APP),
+ 0xFFE3: ("APP3", "Application segment 3", APP),
+ 0xFFE4: ("APP4", "Application segment 4", APP),
+ 0xFFE5: ("APP5", "Application segment 5", APP),
+ 0xFFE6: ("APP6", "Application segment 6", APP),
+ 0xFFE7: ("APP7", "Application segment 7", APP),
+ 0xFFE8: ("APP8", "Application segment 8", APP),
+ 0xFFE9: ("APP9", "Application segment 9", APP),
+ 0xFFEA: ("APP10", "Application segment 10", APP),
+ 0xFFEB: ("APP11", "Application segment 11", APP),
+ 0xFFEC: ("APP12", "Application segment 12", APP),
+ 0xFFED: ("APP13", "Application segment 13", APP),
+ 0xFFEE: ("APP14", "Application segment 14", APP),
+ 0xFFEF: ("APP15", "Application segment 15", APP),
+ 0xFFF0: ("JPG0", "Extension 0", None),
+ 0xFFF1: ("JPG1", "Extension 1", None),
+ 0xFFF2: ("JPG2", "Extension 2", None),
+ 0xFFF3: ("JPG3", "Extension 3", None),
+ 0xFFF4: ("JPG4", "Extension 4", None),
+ 0xFFF5: ("JPG5", "Extension 5", None),
+ 0xFFF6: ("JPG6", "Extension 6", None),
+ 0xFFF7: ("JPG7", "Extension 7", None),
+ 0xFFF8: ("JPG8", "Extension 8", None),
+ 0xFFF9: ("JPG9", "Extension 9", None),
+ 0xFFFA: ("JPG10", "Extension 10", None),
+ 0xFFFB: ("JPG11", "Extension 11", None),
+ 0xFFFC: ("JPG12", "Extension 12", None),
+ 0xFFFD: ("JPG13", "Extension 13", None),
+ 0xFFFE: ("COM", "Comment", COM)
+}
+
+
+def _accept(prefix):
+ return prefix[0] == "\377"
+
+##
+# Image plugin for JPEG and JFIF images.
+
+class JpegImageFile(ImageFile.ImageFile):
+
+ format = "JPEG"
+ format_description = "JPEG (ISO 10918)"
+
+ def _open(self):
+
+ s = self.fp.read(1)
+
+ if ord(s[0]) != 255:
+ raise SyntaxError("not a JPEG file")
+
+ # Create attributes
+ self.bits = self.layers = 0
+
+ # JPEG specifics (internal)
+ self.layer = []
+ self.huffman_dc = {}
+ self.huffman_ac = {}
+ self.quantization = {}
+ self.app = {} # compatibility
+ self.applist = []
+
+ while 1:
+
+ s = s + self.fp.read(1)
+
+ i = i16(s)
+
+ if MARKER.has_key(i):
+ name, description, handler = MARKER[i]
+ # print hex(i), name, description
+ if handler is not None:
+ handler(self, i)
+ if i == 0xFFDA: # start of scan
+ rawmode = self.mode
+ if self.mode == "CMYK":
+ rawmode = "CMYK;I"
+ self.tile = [("jpeg", (0,0) + self.size, 0, (rawmode, ""))]
+ # self.__offset = self.fp.tell()
+ break
+ s = self.fp.read(1)
+ elif i == 0 or i == 65535:
+ # padded marker or junk; move on
+ s = "\xff"
+ else:
+ raise SyntaxError("no marker found")
+
+ def draft(self, mode, size):
+
+ if len(self.tile) != 1:
+ return
+
+ d, e, o, a = self.tile[0]
+ scale = 0
+
+ if a[0] == "RGB" and mode in ["L", "YCbCr"]:
+ self.mode = mode
+ a = mode, ""
+
+ if size:
+ scale = max(self.size[0] / size[0], self.size[1] / size[1])
+ for s in [8, 4, 2, 1]:
+ if scale >= s:
+ break
+ e = e[0], e[1], (e[2]-e[0]+s-1)/s+e[0], (e[3]-e[1]+s-1)/s+e[1]
+ self.size = ((self.size[0]+s-1)/s, (self.size[1]+s-1)/s)
+ scale = s
+
+ self.tile = [(d, e, o, a)]
+ self.decoderconfig = (scale, 1)
+
+ return self
+
+ def load_djpeg(self):
+
+ # ALTERNATIVE: handle JPEGs via the IJG command line utilities
+
+ import tempfile, os
+ file = tempfile.mktemp()
+ os.system("djpeg %s >%s" % (self.filename, file))
+
+ try:
+ self.im = Image.core.open_ppm(file)
+ finally:
+ try: os.unlink(file)
+ except: pass
+
+ self.mode = self.im.mode
+ self.size = self.im.size
+
+ self.tile = []
+
+ def _getexif(self):
+ # Extract EXIF information. This method is highly experimental,
+ # and is likely to be replaced with something better in a future
+ # version.
+ import TiffImagePlugin, StringIO
+ def fixup(value):
+ if len(value) == 1:
+ return value[0]
+ return value
+ # The EXIF record consists of a TIFF file embedded in a JPEG
+ # application marker (!).
+ try:
+ data = self.info["exif"]
+ except KeyError:
+ return None
+ file = StringIO.StringIO(data[6:])
+ head = file.read(8)
+ exif = {}
+ # process dictionary
+ info = TiffImagePlugin.ImageFileDirectory(head)
+ info.load(file)
+ for key, value in info.items():
+ exif[key] = fixup(value)
+ # get exif extension
+ file.seek(exif[0x8769])
+ info = TiffImagePlugin.ImageFileDirectory(head)
+ info.load(file)
+ for key, value in info.items():
+ exif[key] = fixup(value)
+ # get gpsinfo extension
+ try:
+ file.seek(exif[0x8825])
+ except KeyError:
+ pass
+ else:
+ info = TiffImagePlugin.ImageFileDirectory(head)
+ info.load(file)
+ exif[0x8825] = gps = {}
+ for key, value in info.items():
+ gps[key] = fixup(value)
+ return exif
+
+# --------------------------------------------------------------------
+# stuff to save JPEG files
+
+RAWMODE = {
+ "1": "L",
+ "L": "L",
+ "RGB": "RGB",
+ "RGBA": "RGB",
+ "RGBX": "RGB",
+ "CMYK": "CMYK;I",
+ "YCbCr": "YCbCr",
+}
+
+def _save(im, fp, filename):
+
+ try:
+ rawmode = RAWMODE[im.mode]
+ except KeyError:
+ raise IOError("cannot write mode %s as JPEG" % im.mode)
+
+ info = im.encoderinfo
+
+ dpi = info.get("dpi", (0, 0))
+
+ # get keyword arguments
+ im.encoderconfig = (
+ info.get("quality", 0),
+ # "progressive" is the official name, but older documentation
+ # says "progression"
+ # FIXME: issue a warning if the wrong form is used (post-1.1.5)
+ info.has_key("progressive") or info.has_key("progression"),
+ info.get("smooth", 0),
+ info.has_key("optimize"),
+ info.get("streamtype", 0),
+ dpi[0], dpi[1]
+ )
+
+ ImageFile._save(im, fp, [("jpeg", (0,0)+im.size, 0, rawmode)])
+
+def _save_cjpeg(im, fp, filename):
+ # ALTERNATIVE: handle JPEGs via the IJG command line utilities.
+ import os
+ file = im._dump()
+ os.system("cjpeg %s >%s" % (file, filename))
+ try: os.unlink(file)
+ except: pass
+
+# -------------------------------------------------------------------q-
+# Registry stuff
+
+Image.register_open("JPEG", JpegImageFile, _accept)
+Image.register_save("JPEG", _save)
+
+Image.register_extension("JPEG", ".jfif")
+Image.register_extension("JPEG", ".jpe")
+Image.register_extension("JPEG", ".jpg")
+Image.register_extension("JPEG", ".jpeg")
+
+Image.register_mime("JPEG", "image/jpeg")
diff --git a/Imaging/PIL/McIdasImagePlugin.py b/Imaging/PIL/McIdasImagePlugin.py
new file mode 100644
index 0000000..b3b48ec
--- /dev/null
+++ b/Imaging/PIL/McIdasImagePlugin.py
@@ -0,0 +1,74 @@
+#
+# The Python Imaging Library.
+# $Id: McIdasImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# Basic McIdas support for PIL
+#
+# History:
+# 97-05-05 fl Created (8-bit images only)
+#
+# Thanks to Richard Jones <richard.jones@bom.gov.au> for specs
+# and samples.
+#
+# Copyright (c) Secret Labs AB 1997.
+# Copyright (c) Fredrik Lundh 1997.
+#
+# See the README file for information on usage and redistribution.
+#
+
+__version__ = "0.1"
+
+import string
+
+import Image, ImageFile
+
+def i16(c,i=0):
+ return ord(c[1+i])+(ord(c[i])<<8)
+
+def i32(c,i=0):
+ return ord(c[3+i])+(ord(c[2+i])<<8)+(ord(c[1+i])<<16)+(ord(c[i])<<24)
+
+def _accept(s):
+ return i32(s) == 0 and i32(s, 4) == 4
+
+##
+# Image plugin for McIdas area images.
+
+class McIdasImageFile(ImageFile.ImageFile):
+
+ format = "MCIDAS"
+ format_description = "McIdas area file"
+
+ def _open(self):
+
+ # parse area file directory
+ s = self.fp.read(256)
+ if not _accept(s):
+ raise SyntaxError, "not an McIdas area file"
+
+ # get mode
+ if i32(s, 40) != 1 or i32(s, 52) != 1:
+ raise SyntaxError, "unsupported McIdas format"
+
+ self.mode = "L"
+
+ # get size
+ self.size = i32(s, 36), i32(s, 32)
+
+ # setup image descriptor
+ prefix = i32(s, 56)
+ offset = i32(s, 132)
+
+ self.tile = [("raw", (0, 0) + self.size, offset,
+ ("L", prefix + self.size[0], 1))]
+
+ # FIXME: should store the navigation and calibration blocks
+ # somewhere (or perhaps extract some basic information from
+ # them...)
+
+# --------------------------------------------------------------------
+# registry
+
+Image.register_open("MCIDAS", McIdasImageFile, _accept)
+
+# no default extension
diff --git a/Imaging/PIL/MicImagePlugin.py b/Imaging/PIL/MicImagePlugin.py
new file mode 100644
index 0000000..b7b108e
--- /dev/null
+++ b/Imaging/PIL/MicImagePlugin.py
@@ -0,0 +1,96 @@
+#
+# The Python Imaging Library.
+# $Id: MicImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# Microsoft Image Composer support for PIL
+#
+# Notes:
+# uses TiffImagePlugin.py to read the actual image streams
+#
+# History:
+# 97-01-20 fl Created
+#
+# Copyright (c) Secret Labs AB 1997.
+# Copyright (c) Fredrik Lundh 1997.
+#
+# See the README file for information on usage and redistribution.
+#
+
+
+__version__ = "0.1"
+
+import string
+
+import Image, TiffImagePlugin
+from OleFileIO import *
+
+
+#
+# --------------------------------------------------------------------
+
+
+def _accept(prefix):
+ return prefix[:8] == MAGIC
+
+##
+# Image plugin for Microsoft's Image Composer file format.
+
+class MicImageFile(TiffImagePlugin.TiffImageFile):
+
+ format = "MIC"
+ format_description = "Microsoft Image Composer"
+
+ def _open(self):
+
+ # read the OLE directory and see if this is a likely
+ # to be a Microsoft Image Composer file
+
+ try:
+ self.ole = OleFileIO(self.fp)
+ except IOError:
+ raise SyntaxError, "not an MIC file; invalid OLE file"
+
+ # find ACI subfiles with Image members (maybe not the
+ # best way to identify MIC files, but what the... ;-)
+
+ self.images = []
+ for file in self.ole.listdir():
+ if file[1:] and file[0][-4:] == ".ACI" and file[1] == "Image":
+ self.images.append(file)
+
+ # if we didn't find any images, this is probably not
+ # an MIC file.
+ if not self.images:
+ raise SyntaxError, "not an MIC file; no image entries"
+
+ self.__fp = self.fp
+ self.frame = 0
+
+ if len(self.images) > 1:
+ self.category = Image.CONTAINER
+
+ self.seek(0)
+
+ def seek(self, frame):
+
+ try:
+ filename = self.images[frame]
+ except IndexError:
+ raise EOFError, "no such frame"
+
+ self.fp = self.ole.openstream(filename)
+
+ TiffImagePlugin.TiffImageFile._open(self)
+
+ self.frame = frame
+
+ def tell(self):
+
+ return self.frame
+
+#
+# --------------------------------------------------------------------
+
+Image.register_open("MIC", MicImageFile, _accept)
+
+Image.register_extension("MIC", ".mic")
diff --git a/Imaging/PIL/MpegImagePlugin.py b/Imaging/PIL/MpegImagePlugin.py
new file mode 100644
index 0000000..9623c7a
--- /dev/null
+++ b/Imaging/PIL/MpegImagePlugin.py
@@ -0,0 +1,83 @@
+#
+# The Python Imaging Library.
+# $Id: MpegImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# MPEG file handling
+#
+# History:
+# 95-09-09 fl Created
+#
+# Copyright (c) Secret Labs AB 1997.
+# Copyright (c) Fredrik Lundh 1995.
+#
+# See the README file for information on usage and redistribution.
+#
+
+__version__ = "0.1"
+
+import array, string
+import Image, ImageFile
+
+#
+# Bitstream parser
+
+class BitStream:
+
+ def __init__(self, fp):
+ self.fp = fp
+ self.bits = 0
+ self.bitbuffer = 0
+
+ def next(self):
+ return ord(self.fp.read(1))
+
+ def peek(self, bits):
+ while self.bits < bits:
+ c = self.next()
+ if c < 0:
+ self.bits = 0
+ continue
+ self.bitbuffer = (self.bitbuffer << 8) + c
+ self.bits = self.bits + 8
+ return self.bitbuffer >> (self.bits - bits) & (1L << bits) - 1
+
+ def skip(self, bits):
+ while self.bits < bits:
+ self.bitbuffer = (self.bitbuffer << 8) + ord(self.fp.read(1))
+ self.bits = self.bits + 8
+ self.bits = self.bits - bits
+
+ def read(self, bits):
+ v = self.peek(bits)
+ self.bits = self.bits - bits
+ return v
+
+##
+# Image plugin for MPEG streams. This plugin can identify a stream,
+# but it cannot read it.
+
+class MpegImageFile(ImageFile.ImageFile):
+
+ format = "MPEG"
+ format_description = "MPEG"
+
+ def _open(self):
+
+ s = BitStream(self.fp)
+
+ if s.read(32) != 0x1B3:
+ raise SyntaxError, "not an MPEG file"
+
+ self.mode = "RGB"
+ self.size = s.read(12), s.read(12)
+
+
+# --------------------------------------------------------------------
+# Registry stuff
+
+Image.register_open("MPEG", MpegImageFile)
+
+Image.register_extension("MPEG", ".mpg")
+Image.register_extension("MPEG", ".mpeg")
+
+Image.register_mime("MPEG", "video/mpeg")
diff --git a/Imaging/PIL/MspImagePlugin.py b/Imaging/PIL/MspImagePlugin.py
new file mode 100644
index 0000000..40aac19
--- /dev/null
+++ b/Imaging/PIL/MspImagePlugin.py
@@ -0,0 +1,103 @@
+#
+# The Python Imaging Library.
+# $Id: MspImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# MSP file handling
+#
+# This is the format used by the Paint program in Windows 1 and 2.
+#
+# History:
+# 95-09-05 fl Created
+# 97-01-03 fl Read/write MSP images
+#
+# Copyright (c) Secret Labs AB 1997.
+# Copyright (c) Fredrik Lundh 1995-97.
+#
+# See the README file for information on usage and redistribution.
+#
+
+
+__version__ = "0.1"
+
+import Image, ImageFile
+
+
+#
+# read MSP files
+
+def i16(c):
+ return ord(c[0]) + (ord(c[1])<<8)
+
+def _accept(prefix):
+ return prefix[:4] in ["DanM", "LinS"]
+
+##
+# Image plugin for Windows MSP images. This plugin supports both
+# uncompressed (Windows 1.0).
+
+class MspImageFile(ImageFile.ImageFile):
+
+ format = "MSP"
+ format_description = "Windows Paint"
+
+ def _open(self):
+
+ # Header
+ s = self.fp.read(32)
+ if s[:4] not in ["DanM", "LinS"]:
+ raise SyntaxError, "not an MSP file"
+
+ # Header checksum
+ sum = 0
+ for i in range(0, 32, 2):
+ sum = sum ^ i16(s[i:i+2])
+ if sum != 0:
+ raise SyntaxError, "bad MSP checksum"
+
+ self.mode = "1"
+ self.size = i16(s[4:]), i16(s[6:])
+
+ if s[:4] == "DanM":
+ self.tile = [("raw", (0,0)+self.size, 32, ("1", 0, 1))]
+ else:
+ self.tile = [("msp", (0,0)+self.size, 32+2*self.size[1], None)]
+
+#
+# write MSP files (uncompressed only)
+
+def o16(i):
+ return chr(i&255) + chr(i>>8&255)
+
+def _save(im, fp, filename):
+
+ if im.mode != "1":
+ raise IOError, "cannot write mode %s as MSP" % im.mode
+
+ # create MSP header
+ header = [0] * 16
+
+ header[0], header[1] = i16("Da"), i16("nM") # version 1
+ header[2], header[3] = im.size
+ header[4], header[5] = 1, 1
+ header[6], header[7] = 1, 1
+ header[8], header[9] = im.size
+
+ sum = 0
+ for h in header:
+ sum = sum ^ h
+ header[12] = sum # FIXME: is this the right field?
+
+ # header
+ for h in header:
+ fp.write(o16(h))
+
+ # image body
+ ImageFile._save(im, fp, [("raw", (0,0)+im.size, 32, ("1", 0, 1))])
+
+#
+# registry
+
+Image.register_open("MSP", MspImageFile, _accept)
+Image.register_save("MSP", _save)
+
+Image.register_extension("MSP", ".msp")
diff --git a/Imaging/PIL/OleFileIO.py b/Imaging/PIL/OleFileIO.py
new file mode 100644
index 0000000..9383eca
--- /dev/null
+++ b/Imaging/PIL/OleFileIO.py
@@ -0,0 +1,528 @@
+#
+# THIS IS WORK IN PROGRESS
+#
+# The Python Imaging Library
+# $Id: OleFileIO.py 2339 2005-03-25 08:02:17Z fredrik $
+#
+# stuff to deal with OLE2 Structured Storage files. this module is
+# used by PIL to read Image Composer and FlashPix files, but can also
+# be used to read other files of this type.
+#
+# History:
+# 1997-01-20 fl Created
+# 1997-01-22 fl Fixed 64-bit portability quirk
+# 2003-09-09 fl Fixed typo in OleFileIO.loadfat (noted by Daniel Haertle)
+# 2004-02-29 fl Changed long hex constants to signed integers
+#
+# Notes:
+# FIXME: sort out sign problem (eliminate long hex constants)
+# FIXME: change filename to use "a/b/c" instead of ["a", "b", "c"]
+# FIXME: provide a glob mechanism function (using fnmatchcase)
+#
+# Literature:
+#
+# "FlashPix Format Specification, Appendix A", Kodak and Microsoft,
+# September 1996.
+#
+# Quotes:
+#
+# "If this document and functionality of the Software conflict,
+# the actual functionality of the Software represents the correct
+# functionality" -- Microsoft, in the OLE format specification
+#
+# Copyright (c) Secret Labs AB 1997.
+# Copyright (c) Fredrik Lundh 1997.
+#
+# See the README file for information on usage and redistribution.
+#
+
+import string, StringIO
+
+
+def i16(c, o = 0):
+ return ord(c[o])+(ord(c[o+1])<<8)
+
+def i32(c, o = 0):
+ return ord(c[o])+(ord(c[o+1])<<8)+(ord(c[o+2])<<16)+(ord(c[o+3])<<24)
+
+
+MAGIC = '\320\317\021\340\241\261\032\341'
+
+#
+# --------------------------------------------------------------------
+# property types
+
+VT_EMPTY=0; VT_NULL=1; VT_I2=2; VT_I4=3; VT_R4=4; VT_R8=5; VT_CY=6;
+VT_DATE=7; VT_BSTR=8; VT_DISPATCH=9; VT_ERROR=10; VT_BOOL=11;
+VT_VARIANT=12; VT_UNKNOWN=13; VT_DECIMAL=14; VT_I1=16; VT_UI1=17;
+VT_UI2=18; VT_UI4=19; VT_I8=20; VT_UI8=21; VT_INT=22; VT_UINT=23;
+VT_VOID=24; VT_HRESULT=25; VT_PTR=26; VT_SAFEARRAY=27; VT_CARRAY=28;
+VT_USERDEFINED=29; VT_LPSTR=30; VT_LPWSTR=31; VT_FILETIME=64;
+VT_BLOB=65; VT_STREAM=66; VT_STORAGE=67; VT_STREAMED_OBJECT=68;
+VT_STORED_OBJECT=69; VT_BLOB_OBJECT=70; VT_CF=71; VT_CLSID=72;
+VT_VECTOR=0x1000;
+
+# map property id to name (for debugging purposes)
+
+VT = {}
+for k, v in vars().items():
+ if k[:3] == "VT_":
+ VT[v] = k
+
+#
+# --------------------------------------------------------------------
+# Some common document types (root.clsid fields)
+
+WORD_CLSID = "00020900-0000-0000-C000-000000000046"
+
+
+#
+# --------------------------------------------------------------------
+
+class _OleStream(StringIO.StringIO):
+
+ """OLE2 Stream
+
+ Returns a read-only file object which can be used to read
+ the contents of a OLE stream. To open a stream, use the
+ openstream method in the OleFile class.
+
+ This function can be used with either ordinary streams,
+ or ministreams, depending on the offset, sectorsize, and
+ fat table arguments.
+ """
+
+ # FIXME: should store the list of sects obtained by following
+ # the fat chain, and load new sectors on demand instead of
+ # loading it all in one go.
+
+ def __init__(self, fp, sect, size, offset, sectorsize, fat):
+
+ data = []
+
+ while sect != -2: # 0xFFFFFFFEL:
+ fp.seek(offset + sectorsize * sect)
+ data.append(fp.read(sectorsize))
+ sect = fat[sect]
+
+ data = string.join(data, "")
+
+ # print len(data), size
+
+ StringIO.StringIO.__init__(self, data[:size])
+
+#
+# --------------------------------------------------------------------
+
+# FIXME: should add a counter in here to avoid looping forever
+# if the tree is broken.
+
+class _OleDirectoryEntry:
+
+ """OLE2 Directory Entry
+
+ Encapsulates a stream directory entry. Note that the
+ constructor builds a tree of all subentries, so we only
+ have to call it with the root object.
+ """
+
+ def __init__(self, sidlist, sid):
+
+ # store directory parameters. the caller provides
+ # a complete list of directory entries, as read from
+ # the directory stream.
+
+ name, type, sect, size, sids, clsid = sidlist[sid]
+
+ self.sid = sid
+ self.name = name
+ self.type = type # 1=storage 2=stream
+ self.sect = sect
+ self.size = size
+ self.clsid = clsid
+
+ # process child nodes, if any
+
+ self.kids = []
+
+ sid = sidlist[sid][4][2]
+
+ if sid != -1:
+
+ # the directory entries are organized as a red-black tree.
+ # the following piece of code does an ordered traversal of
+ # such a tree (at least that's what I hope ;-)
+
+ stack = [self.sid]
+
+ # start at leftmost position
+
+ left, right, child = sidlist[sid][4]
+
+ while left != -1: # 0xFFFFFFFFL:
+ stack.append(sid)
+ sid = left
+ left, right, child = sidlist[sid][4]
+
+ while sid != self.sid:
+
+ self.kids.append(_OleDirectoryEntry(sidlist, sid))
+
+ # try to move right
+ left, right, child = sidlist[sid][4]
+ if right != -1: # 0xFFFFFFFFL:
+ # and then back to the left
+ sid = right
+ while 1:
+ left, right, child = sidlist[sid][4]
+ if left == -1: # 0xFFFFFFFFL:
+ break
+ stack.append(sid)
+ sid = left
+ else:
+ # couldn't move right; move up instead
+ while 1:
+ ptr = stack[-1]
+ del stack[-1]
+ left, right, child = sidlist[ptr][4]
+ if right != sid:
+ break
+ sid = right
+ left, right, child = sidlist[sid][4]
+ if right != ptr:
+ sid = ptr
+
+ # in the OLE file, entries are sorted on (length, name).
+ # for convenience, we sort them on name instead.
+
+ self.kids.sort()
+
+ def __cmp__(self, other):
+ "Compare entries by name"
+
+ return cmp(self.name, other.name)
+
+ def dump(self, tab = 0):
+ "Dump this entry, and all its subentries (for debug purposes only)"
+
+ TYPES = ["(invalid)", "(storage)", "(stream)", "(lockbytes)",
+ "(property)", "(root)"]
+
+ print " "*tab + repr(self.name), TYPES[self.type],
+ if self.type in (2, 5):
+ print self.size, "bytes",
+ print
+ if self.type in (1, 5) and self.clsid:
+ print " "*tab + "{%s}" % self.clsid
+
+ for kid in self.kids:
+ kid.dump(tab + 2)
+
+#
+# --------------------------------------------------------------------
+
+##
+# This class encapsulates the interface to an OLE 2 structured
+# storage file. Use the {@link listdir} and {@link openstream}
+# methods to access the contents of this file.
+
+class OleFileIO:
+ """OLE container object
+
+ This class encapsulates the interface to an OLE 2 structured
+ storage file. Use the listdir and openstream methods to access
+ the contents of this file.
+
+ Object names are given as a list of strings, one for each subentry
+ level. The root entry should be omitted. For example, the following
+ code extracts all image streams from a Microsoft Image Composer file:
+
+ ole = OleFileIO("fan.mic")
+
+ for entry in ole.listdir():
+ if entry[1:2] == "Image":
+ fin = ole.openstream(entry)
+ fout = open(entry[0:1], "wb")
+ while 1:
+ s = fin.read(8192)
+ if not s:
+ break
+ fout.write(s)
+
+ You can use the viewer application provided with the Python Imaging
+ Library to view the resulting files (which happens to be standard
+ TIFF files).
+ """
+
+ def __init__(self, filename = None):
+
+ if filename:
+ self.open(filename)
+
+ ##
+ # Open an OLE2 file.
+
+ def open(self, filename):
+ """Open an OLE2 file"""
+
+ if type(filename) == type(""):
+ self.fp = open(filename, "rb")
+ else:
+ self.fp = filename
+
+ header = self.fp.read(512)
+
+ if len(header) != 512 or header[:8] != MAGIC:
+ raise IOError, "not an OLE2 structured storage file"
+
+ # file clsid (probably never used, so we don't store it)
+ clsid = self._clsid(header[8:24])
+
+ # FIXME: could check version and byte order fields
+
+ self.sectorsize = 1 << i16(header, 30)
+ self.minisectorsize = 1 << i16(header, 32)
+
+ self.minisectorcutoff = i32(header, 56)
+
+ # Load file allocation tables
+ self.loadfat(header)
+
+ # Load direcory. This sets both the sidlist (ordered by id)
+ # and the root (ordered by hierarchy) members.
+ self.loaddirectory(i32(header, 48))
+
+ self.ministream = None
+ self.minifatsect = i32(header, 60)
+
+ def loadfat(self, header):
+ # Load the FAT table. The header contains a sector numbers
+ # for the first 109 FAT sectors. Additional sectors are
+ # described by DIF blocks (FIXME: not yet implemented)
+
+ sect = header[76:512]
+ fat = []
+ for i in range(0, len(sect), 4):
+ ix = i32(sect, i)
+ if ix == -2 or ix == -1: # ix == 0xFFFFFFFEL or ix == 0xFFFFFFFFL:
+ break
+ s = self.getsect(ix)
+ fat = fat + map(lambda i, s=s: i32(s, i), range(0, len(s), 4))
+ self.fat = fat
+
+ def loadminifat(self):
+ # Load the MINIFAT table. This is stored in a standard sub-
+ # stream, pointed to by a header field.
+
+ s = self._open(self.minifatsect).read()
+
+ self.minifat = map(lambda i, s=s: i32(s, i), range(0, len(s), 4))
+
+ def getsect(self, sect):
+ # Read given sector
+
+ self.fp.seek(512 + self.sectorsize * sect)
+ return self.fp.read(self.sectorsize)
+
+ def _unicode(self, s):
+ # Map unicode string to Latin 1
+
+ # FIXME: some day, Python will provide an official way to handle
+ # Unicode strings, but until then, this will have to do...
+ return filter(ord, s)
+
+ def loaddirectory(self, sect):
+ # Load the directory. The directory is stored in a standard
+ # substream, independent of its size.
+
+ # read directory stream
+ fp = self._open(sect)
+
+ # create list of sid entries
+ self.sidlist = []
+ while 1:
+ entry = fp.read(128)
+ if not entry:
+ break
+ type = ord(entry[66])
+ name = self._unicode(entry[0:0+i16(entry, 64)])
+ ptrs = i32(entry, 68), i32(entry, 72), i32(entry, 76)
+ sect, size = i32(entry, 116), i32(entry, 120)
+ clsid = self._clsid(entry[80:96])
+ self.sidlist.append((name, type, sect, size, ptrs, clsid))
+
+ # create hierarchical list of directory entries
+ self.root = _OleDirectoryEntry(self.sidlist, 0)
+
+ def dumpdirectory(self):
+ # Dump directory (for debugging only)
+
+ self.root.dump()
+
+ def _clsid(self, clsid):
+ if clsid == "\0" * len(clsid):
+ return ""
+ return (("%08X-%04X-%04X-%02X%02X-" + "%02X" * 6) %
+ ((i32(clsid, 0), i16(clsid, 4), i16(clsid, 6)) +
+ tuple(map(ord, clsid[8:16]))))
+
+ def _list(self, files, prefix, node):
+ # listdir helper
+
+ prefix = prefix + [node.name]
+ for entry in node.kids:
+ if entry.kids:
+ self._list(files, prefix, entry)
+ else:
+ files.append(prefix[1:] + [entry.name])
+
+ def _find(self, filename):
+ # openstream helper
+
+ node = self.root
+ for name in filename:
+ for kid in node.kids:
+ if kid.name == name:
+ break
+ else:
+ raise IOError, "file not found"
+ node = kid
+ return node.sid
+
+ def _open(self, start, size = 0x7FFFFFFF):
+ # openstream helper.
+
+ if size < self.minisectorcutoff:
+ # ministream object
+ if not self.ministream:
+ self.loadminifat()
+ self.ministream = self._open(self.sidlist[0][2])
+ return _OleStream(self.ministream, start, size, 0,
+ self.minisectorsize, self.minifat)
+
+ # standard stream
+ return _OleStream(self.fp, start, size, 512,
+ self.sectorsize, self.fat)
+
+ ##
+ # Returns a list of streams stored in this file.
+
+ def listdir(self):
+ """Return a list of streams stored in this file"""
+
+ files = []
+ self._list(files, [], self.root)
+ return files
+
+ ##
+ # Opens a stream as a read-only file object.
+
+ def openstream(self, filename):
+ """Open a stream as a read-only file object"""
+
+ slot = self._find(filename)
+ name, type, sect, size, sids, clsid = self.sidlist[slot]
+ if type != 2:
+ raise IOError, "this file is not a stream"
+ return self._open(sect, size)
+
+ ##
+ # Gets a list of properties described in substream.
+
+ def getproperties(self, filename):
+ """Return properties described in substream"""
+
+ fp = self.openstream(filename)
+
+ data = {}
+
+ # header
+ s = fp.read(28)
+ clsid = self._clsid(s[8:24])
+
+ # format id
+ s = fp.read(20)
+ fmtid = self._clsid(s[:16])
+ fp.seek(i32(s, 16))
+
+ # get section
+ s = "****" + fp.read(i32(fp.read(4))-4)
+
+ for i in range(i32(s, 4)):
+
+ id = i32(s, 8+i*8)
+ offset = i32(s, 12+i*8)
+ type = i32(s, offset)
+
+ # test for common types first (should perhaps use
+ # a dictionary instead?)
+
+ if type == VT_I2:
+ value = i16(s, offset+4)
+ if value >= 32768:
+ value = value - 65536
+ elif type == VT_UI2:
+ value = i16(s, offset+4)
+ elif type in (VT_I4, VT_ERROR):
+ value = i32(s, offset+4)
+ elif type == VT_UI4:
+ value = i32(s, offset+4) # FIXME
+ elif type in (VT_BSTR, VT_LPSTR):
+ count = i32(s, offset+4)
+ value = s[offset+8:offset+8+count-1]
+ elif type == VT_BLOB:
+ count = i32(s, offset+4)
+ value = s[offset+8:offset+8+count]
+ elif type == VT_LPWSTR:
+ count = i32(s, offset+4)
+ value = self._unicode(s[offset+8:offset+8+count*2])
+ elif type == VT_FILETIME:
+ value = long(i32(s, offset+4)) + (long(i32(s, offset+8))<<32)
+ # FIXME: this is a 64-bit int: "number of 100ns periods
+ # since Jan 1,1601". Should map this to Python time
+ value = value / 10000000L # seconds
+ elif type == VT_UI1:
+ value = ord(s[offset+4])
+ elif type == VT_CLSID:
+ value = self._clsid(s[offset+4:offset+20])
+ elif type == VT_CF:
+ count = i32(s, offset+4)
+ value = s[offset+8:offset+8+count]
+ else:
+ value = None # everything else yields "None"
+
+ # FIXME: add support for VT_VECTOR
+
+ #print "%08x" % id, repr(value),
+ #print "(%s)" % VT[i32(s, offset) & 0xFFF]
+
+ data[id] = value
+
+ return data
+
+#
+# --------------------------------------------------------------------
+# This script can be used to dump the directory of any OLE2 structured
+# storage file.
+
+if __name__ == "__main__":
+
+ import sys
+
+ for file in sys.argv[1:]:
+ try:
+ ole = OleFileIO(file)
+ print "-" * 68
+ print file
+ print "-" * 68
+ ole.dumpdirectory()
+ for file in ole.listdir():
+ if file[-1][0] == "\005":
+ print file
+ props = ole.getproperties(file)
+ props = props.items()
+ props.sort()
+ for k, v in props:
+ print " ", k, v
+ except IOError, v:
+ print "***", "cannot read", file, "-", v
diff --git a/Imaging/PIL/PSDraw.py b/Imaging/PIL/PSDraw.py
new file mode 100644
index 0000000..7e88f55
--- /dev/null
+++ b/Imaging/PIL/PSDraw.py
@@ -0,0 +1,199 @@
+#
+# The Python Imaging Library
+# $Id: PSDraw.py 2813 2006-10-07 10:11:35Z fredrik $
+#
+# simple postscript graphics interface
+#
+# History:
+# 1996-04-20 fl Created
+# 1999-01-10 fl Added gsave/grestore to image method
+# 2005-05-04 fl Fixed floating point issue in image (from Eric Etheridge)
+#
+# Copyright (c) 1997-2005 by Secret Labs AB. All rights reserved.
+# Copyright (c) 1996 by Fredrik Lundh.
+#
+# See the README file for information on usage and redistribution.
+#
+
+import EpsImagePlugin
+import string
+
+##
+# Simple Postscript graphics interface.
+
+class PSDraw:
+
+ def __init__(self, fp=None):
+ if not fp:
+ import sys
+ fp = sys.stdout
+ self.fp = fp
+
+ def begin_document(self, id = None):
+ "Write Postscript DSC header"
+ # FIXME: incomplete
+ self.fp.write("%!PS-Adobe-3.0\n"
+ "save\n"
+ "/showpage { } def\n"
+ "%%EndComments\n"
+ "%%BeginDocument\n")
+ #self.fp.write(ERROR_PS) # debugging!
+ self.fp.write(EDROFF_PS)
+ self.fp.write(VDI_PS)
+ self.fp.write("%%EndProlog\n")
+ self.isofont = {}
+
+ def end_document(self):
+ "Write Postscript DSC footer"
+ self.fp.write("%%EndDocument\n"
+ "restore showpage\n"
+ "%%End\n")
+ if hasattr(self.fp, "flush"):
+ self.fp.flush()
+
+ def setfont(self, font, size):
+ if not self.isofont.has_key(font):
+ # reencode font
+ self.fp.write("/PSDraw-%s ISOLatin1Encoding /%s E\n" %\
+ (font, font))
+ self.isofont[font] = 1
+ # rough
+ self.fp.write("/F0 %d /PSDraw-%s F\n" % (size, font))
+
+ def setink(self, ink):
+ print "*** NOT YET IMPLEMENTED ***"
+
+ def line(self, xy0, xy1):
+ xy = xy0 + xy1
+ self.fp.write("%d %d %d %d Vl\n" % xy)
+
+ def rectangle(self, box):
+ self.fp.write("%d %d M %d %d 0 Vr\n" % box)
+
+ def text(self, xy, text):
+ text = string.joinfields(string.splitfields(text, "("), "\\(")
+ text = string.joinfields(string.splitfields(text, ")"), "\\)")
+ xy = xy + (text,)
+ self.fp.write("%d %d M (%s) S\n" % xy)
+
+ def image(self, box, im, dpi = None):
+ "Write an PIL image"
+ # default resolution depends on mode
+ if not dpi:
+ if im.mode == "1":
+ dpi = 200 # fax
+ else:
+ dpi = 100 # greyscale
+ # image size (on paper)
+ x = float(im.size[0] * 72) / dpi
+ y = float(im.size[1] * 72) / dpi
+ # max allowed size
+ xmax = float(box[2] - box[0])
+ ymax = float(box[3] - box[1])
+ if x > xmax:
+ y = y * xmax / x; x = xmax
+ if y > ymax:
+ x = x * ymax / y; y = ymax
+ dx = (xmax - x) / 2 + box[0]
+ dy = (ymax - y) / 2 + box[1]
+ self.fp.write("gsave\n%f %f translate\n" % (dx, dy))
+ if (x, y) != im.size:
+ # EpsImagePlugin._save prints the image at (0,0,xsize,ysize)
+ sx = x / im.size[0]
+ sy = y / im.size[1]
+ self.fp.write("%f %f scale\n" % (sx, sy))
+ EpsImagePlugin._save(im, self.fp, None, 0)
+ self.fp.write("\ngrestore\n")
+
+# --------------------------------------------------------------------
+# Postscript driver
+
+#
+# EDROFF.PS -- Postscript driver for Edroff 2
+#
+# History:
+# 94-01-25 fl: created (edroff 2.04)
+#
+# Copyright (c) Fredrik Lundh 1994.
+#
+
+EDROFF_PS = """\
+/S { show } bind def
+/P { moveto show } bind def
+/M { moveto } bind def
+/X { 0 rmoveto } bind def
+/Y { 0 exch rmoveto } bind def
+/E { findfont
+ dup maxlength dict begin
+ {
+ 1 index /FID ne { def } { pop pop } ifelse
+ } forall
+ /Encoding exch def
+ dup /FontName exch def
+ currentdict end definefont pop
+} bind def
+/F { findfont exch scalefont dup setfont
+ [ exch /setfont cvx ] cvx bind def
+} bind def
+"""
+
+#
+# VDI.PS -- Postscript driver for VDI meta commands
+#
+# History:
+# 94-01-25 fl: created (edroff 2.04)
+#
+# Copyright (c) Fredrik Lundh 1994.
+#
+
+VDI_PS = """\
+/Vm { moveto } bind def
+/Va { newpath arcn stroke } bind def
+/Vl { moveto lineto stroke } bind def
+/Vc { newpath 0 360 arc closepath } bind def
+/Vr { exch dup 0 rlineto
+ exch dup neg 0 exch rlineto
+ exch neg 0 rlineto
+ 0 exch rlineto
+ 100 div setgray fill 0 setgray } bind def
+/Tm matrix def
+/Ve { Tm currentmatrix pop
+ translate scale newpath 0 0 .5 0 360 arc closepath
+ Tm setmatrix
+} bind def
+/Vf { currentgray exch setgray fill setgray } bind def
+"""
+
+#
+# ERROR.PS -- Error handler
+#
+# History:
+# 89-11-21 fl: created (pslist 1.10)
+#
+
+ERROR_PS = """\
+/landscape false def
+/errorBUF 200 string def
+/errorNL { currentpoint 10 sub exch pop 72 exch moveto } def
+errordict begin /handleerror {
+ initmatrix /Courier findfont 10 scalefont setfont
+ newpath 72 720 moveto $error begin /newerror false def
+ (PostScript Error) show errorNL errorNL
+ (Error: ) show
+ /errorname load errorBUF cvs show errorNL errorNL
+ (Command: ) show
+ /command load dup type /stringtype ne { errorBUF cvs } if show
+ errorNL errorNL
+ (VMstatus: ) show
+ vmstatus errorBUF cvs show ( bytes available, ) show
+ errorBUF cvs show ( bytes used at level ) show
+ errorBUF cvs show errorNL errorNL
+ (Operand stargck: ) show errorNL /ostargck load {
+ dup type /stringtype ne { errorBUF cvs } if 72 0 rmoveto show errorNL
+ } forall errorNL
+ (Execution stargck: ) show errorNL /estargck load {
+ dup type /stringtype ne { errorBUF cvs } if 72 0 rmoveto show errorNL
+ } forall
+ end showpage
+} def end
+"""
diff --git a/Imaging/PIL/PaletteFile.py b/Imaging/PIL/PaletteFile.py
new file mode 100644
index 0000000..bbbebfa
--- /dev/null
+++ b/Imaging/PIL/PaletteFile.py
@@ -0,0 +1,53 @@
+#
+# Python Imaging Library
+# $Id: PaletteFile.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# stuff to read simple, teragon-style palette files
+#
+# History:
+# 97-08-23 fl Created
+#
+# Copyright (c) Secret Labs AB 1997.
+# Copyright (c) Fredrik Lundh 1997.
+#
+# See the README file for information on usage and redistribution.
+#
+
+import string
+
+##
+# File handler for Teragon-style palette files.
+
+class PaletteFile:
+
+ rawmode = "RGB"
+
+ def __init__(self, fp):
+
+ self.palette = map(lambda i: (i, i, i), range(256))
+
+ while 1:
+
+ s = fp.readline()
+
+ if not s:
+ break
+ if len(s) > 100:
+ raise SyntaxError, "bad palette file"
+
+ v = map(int, string.split(s))
+ try:
+ [i, r, g, b] = v
+ except ValueError:
+ [i, r] = v
+ g = b = r
+
+ if 0 <= i <= 255:
+ self.palette[i] = chr(r) + chr(g) + chr(b)
+
+ self.palette = string.join(self.palette, "")
+
+
+ def getpalette(self):
+
+ return self.palette, self.rawmode
diff --git a/Imaging/PIL/PalmImagePlugin.py b/Imaging/PIL/PalmImagePlugin.py
new file mode 100644
index 0000000..19f0c2f
--- /dev/null
+++ b/Imaging/PIL/PalmImagePlugin.py
@@ -0,0 +1,226 @@
+#
+# The Python Imaging Library.
+# $Id: PalmImagePlugin.py 2438 2005-05-25 21:09:48Z Fredrik $
+#
+
+##
+# Image plugin for Palm pixmap images (output only).
+##
+
+__version__ = "1.0"
+
+import Image, ImageFile
+import StringIO
+
+_Palm8BitColormapValues = (
+ ( 255, 255, 255 ), ( 255, 204, 255 ), ( 255, 153, 255 ), ( 255, 102, 255 ),
+ ( 255, 51, 255 ), ( 255, 0, 255 ), ( 255, 255, 204 ), ( 255, 204, 204 ),
+ ( 255, 153, 204 ), ( 255, 102, 204 ), ( 255, 51, 204 ), ( 255, 0, 204 ),
+ ( 255, 255, 153 ), ( 255, 204, 153 ), ( 255, 153, 153 ), ( 255, 102, 153 ),
+ ( 255, 51, 153 ), ( 255, 0, 153 ), ( 204, 255, 255 ), ( 204, 204, 255 ),
+ ( 204, 153, 255 ), ( 204, 102, 255 ), ( 204, 51, 255 ), ( 204, 0, 255 ),
+ ( 204, 255, 204 ), ( 204, 204, 204 ), ( 204, 153, 204 ), ( 204, 102, 204 ),
+ ( 204, 51, 204 ), ( 204, 0, 204 ), ( 204, 255, 153 ), ( 204, 204, 153 ),
+ ( 204, 153, 153 ), ( 204, 102, 153 ), ( 204, 51, 153 ), ( 204, 0, 153 ),
+ ( 153, 255, 255 ), ( 153, 204, 255 ), ( 153, 153, 255 ), ( 153, 102, 255 ),
+ ( 153, 51, 255 ), ( 153, 0, 255 ), ( 153, 255, 204 ), ( 153, 204, 204 ),
+ ( 153, 153, 204 ), ( 153, 102, 204 ), ( 153, 51, 204 ), ( 153, 0, 204 ),
+ ( 153, 255, 153 ), ( 153, 204, 153 ), ( 153, 153, 153 ), ( 153, 102, 153 ),
+ ( 153, 51, 153 ), ( 153, 0, 153 ), ( 102, 255, 255 ), ( 102, 204, 255 ),
+ ( 102, 153, 255 ), ( 102, 102, 255 ), ( 102, 51, 255 ), ( 102, 0, 255 ),
+ ( 102, 255, 204 ), ( 102, 204, 204 ), ( 102, 153, 204 ), ( 102, 102, 204 ),
+ ( 102, 51, 204 ), ( 102, 0, 204 ), ( 102, 255, 153 ), ( 102, 204, 153 ),
+ ( 102, 153, 153 ), ( 102, 102, 153 ), ( 102, 51, 153 ), ( 102, 0, 153 ),
+ ( 51, 255, 255 ), ( 51, 204, 255 ), ( 51, 153, 255 ), ( 51, 102, 255 ),
+ ( 51, 51, 255 ), ( 51, 0, 255 ), ( 51, 255, 204 ), ( 51, 204, 204 ),
+ ( 51, 153, 204 ), ( 51, 102, 204 ), ( 51, 51, 204 ), ( 51, 0, 204 ),
+ ( 51, 255, 153 ), ( 51, 204, 153 ), ( 51, 153, 153 ), ( 51, 102, 153 ),
+ ( 51, 51, 153 ), ( 51, 0, 153 ), ( 0, 255, 255 ), ( 0, 204, 255 ),
+ ( 0, 153, 255 ), ( 0, 102, 255 ), ( 0, 51, 255 ), ( 0, 0, 255 ),
+ ( 0, 255, 204 ), ( 0, 204, 204 ), ( 0, 153, 204 ), ( 0, 102, 204 ),
+ ( 0, 51, 204 ), ( 0, 0, 204 ), ( 0, 255, 153 ), ( 0, 204, 153 ),
+ ( 0, 153, 153 ), ( 0, 102, 153 ), ( 0, 51, 153 ), ( 0, 0, 153 ),
+ ( 255, 255, 102 ), ( 255, 204, 102 ), ( 255, 153, 102 ), ( 255, 102, 102 ),
+ ( 255, 51, 102 ), ( 255, 0, 102 ), ( 255, 255, 51 ), ( 255, 204, 51 ),
+ ( 255, 153, 51 ), ( 255, 102, 51 ), ( 255, 51, 51 ), ( 255, 0, 51 ),
+ ( 255, 255, 0 ), ( 255, 204, 0 ), ( 255, 153, 0 ), ( 255, 102, 0 ),
+ ( 255, 51, 0 ), ( 255, 0, 0 ), ( 204, 255, 102 ), ( 204, 204, 102 ),
+ ( 204, 153, 102 ), ( 204, 102, 102 ), ( 204, 51, 102 ), ( 204, 0, 102 ),
+ ( 204, 255, 51 ), ( 204, 204, 51 ), ( 204, 153, 51 ), ( 204, 102, 51 ),
+ ( 204, 51, 51 ), ( 204, 0, 51 ), ( 204, 255, 0 ), ( 204, 204, 0 ),
+ ( 204, 153, 0 ), ( 204, 102, 0 ), ( 204, 51, 0 ), ( 204, 0, 0 ),
+ ( 153, 255, 102 ), ( 153, 204, 102 ), ( 153, 153, 102 ), ( 153, 102, 102 ),
+ ( 153, 51, 102 ), ( 153, 0, 102 ), ( 153, 255, 51 ), ( 153, 204, 51 ),
+ ( 153, 153, 51 ), ( 153, 102, 51 ), ( 153, 51, 51 ), ( 153, 0, 51 ),
+ ( 153, 255, 0 ), ( 153, 204, 0 ), ( 153, 153, 0 ), ( 153, 102, 0 ),
+ ( 153, 51, 0 ), ( 153, 0, 0 ), ( 102, 255, 102 ), ( 102, 204, 102 ),
+ ( 102, 153, 102 ), ( 102, 102, 102 ), ( 102, 51, 102 ), ( 102, 0, 102 ),
+ ( 102, 255, 51 ), ( 102, 204, 51 ), ( 102, 153, 51 ), ( 102, 102, 51 ),
+ ( 102, 51, 51 ), ( 102, 0, 51 ), ( 102, 255, 0 ), ( 102, 204, 0 ),
+ ( 102, 153, 0 ), ( 102, 102, 0 ), ( 102, 51, 0 ), ( 102, 0, 0 ),
+ ( 51, 255, 102 ), ( 51, 204, 102 ), ( 51, 153, 102 ), ( 51, 102, 102 ),
+ ( 51, 51, 102 ), ( 51, 0, 102 ), ( 51, 255, 51 ), ( 51, 204, 51 ),
+ ( 51, 153, 51 ), ( 51, 102, 51 ), ( 51, 51, 51 ), ( 51, 0, 51 ),
+ ( 51, 255, 0 ), ( 51, 204, 0 ), ( 51, 153, 0 ), ( 51, 102, 0 ),
+ ( 51, 51, 0 ), ( 51, 0, 0 ), ( 0, 255, 102 ), ( 0, 204, 102 ),
+ ( 0, 153, 102 ), ( 0, 102, 102 ), ( 0, 51, 102 ), ( 0, 0, 102 ),
+ ( 0, 255, 51 ), ( 0, 204, 51 ), ( 0, 153, 51 ), ( 0, 102, 51 ),
+ ( 0, 51, 51 ), ( 0, 0, 51 ), ( 0, 255, 0 ), ( 0, 204, 0 ),
+ ( 0, 153, 0 ), ( 0, 102, 0 ), ( 0, 51, 0 ), ( 17, 17, 17 ),
+ ( 34, 34, 34 ), ( 68, 68, 68 ), ( 85, 85, 85 ), ( 119, 119, 119 ),
+ ( 136, 136, 136 ), ( 170, 170, 170 ), ( 187, 187, 187 ), ( 221, 221, 221 ),
+ ( 238, 238, 238 ), ( 192, 192, 192 ), ( 128, 0, 0 ), ( 128, 0, 128 ),
+ ( 0, 128, 0 ), ( 0, 128, 128 ), ( 0, 0, 0 ), ( 0, 0, 0 ),
+ ( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ),
+ ( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ),
+ ( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ),
+ ( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ),
+ ( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ),
+ ( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ))
+
+# so build a prototype image to be used for palette resampling
+def build_prototype_image():
+ image = Image.new("L", (1,len(_Palm8BitColormapValues),))
+ image.putdata(range(len(_Palm8BitColormapValues)))
+ palettedata = ()
+ for i in range(len(_Palm8BitColormapValues)):
+ palettedata = palettedata + _Palm8BitColormapValues[i]
+ for i in range(256 - len(_Palm8BitColormapValues)):
+ palettedata = palettedata + (0, 0, 0)
+ image.putpalette(palettedata)
+ return image
+
+Palm8BitColormapImage = build_prototype_image()
+
+# OK, we now have in Palm8BitColormapImage, a "P"-mode image with the right palette
+#
+# --------------------------------------------------------------------
+
+_FLAGS = {
+ "custom-colormap": 0x4000,
+ "is-compressed": 0x8000,
+ "has-transparent": 0x2000,
+ }
+
+_COMPRESSION_TYPES = {
+ "none": 0xFF,
+ "rle": 0x01,
+ "scanline": 0x00,
+ }
+
+def o16b(i):
+ return chr(i>>8&255) + chr(i&255)
+
+#
+# --------------------------------------------------------------------
+
+##
+# (Internal) Image save plugin for the Palm format.
+
+def _save(im, fp, filename, check=0):
+
+ if im.mode == "P":
+
+ # we assume this is a color Palm image with the standard colormap,
+ # unless the "info" dict has a "custom-colormap" field
+
+ rawmode = "P"
+ bpp = 8
+ version = 1
+
+ elif im.mode == "L" and im.encoderinfo.has_key("bpp") and im.encoderinfo["bpp"] in (1, 2, 4):
+
+ # this is 8-bit grayscale, so we shift it to get the high-order bits, and invert it because
+ # Palm does greyscale from white (0) to black (1)
+ bpp = im.encoderinfo["bpp"]
+ im = im.point(lambda x, shift=8-bpp, maxval=(1 << bpp)-1: maxval - (x >> shift))
+ # we ignore the palette here
+ im.mode = "P"
+ rawmode = "P;" + str(bpp)
+ version = 1
+
+ elif im.mode == "L" and im.info.has_key("bpp") and im.info["bpp"] in (1, 2, 4):
+
+ # here we assume that even though the inherent mode is 8-bit grayscale, only
+ # the lower bpp bits are significant. We invert them to match the Palm.
+ bpp = im.info["bpp"]
+ im = im.point(lambda x, maxval=(1 << bpp)-1: maxval - (x & maxval))
+ # we ignore the palette here
+ im.mode = "P"
+ rawmode = "P;" + str(bpp)
+ version = 1
+
+ elif im.mode == "1":
+
+ # monochrome -- write it inverted, as is the Palm standard
+ rawmode = "1;I"
+ bpp = 1
+ version = 0
+
+ else:
+
+ raise IOError, "cannot write mode %s as Palm" % im.mode
+
+ if check:
+ return check
+
+ #
+ # make sure image data is available
+ im.load()
+
+ # write header
+
+ cols = im.size[0]
+ rows = im.size[1]
+
+ rowbytes = ((cols + (16/bpp - 1)) / (16 / bpp)) * 2;
+ transparent_index = 0
+ compression_type = _COMPRESSION_TYPES["none"]
+
+ flags = 0;
+ if im.mode == "P" and im.info.has_key("custom-colormap"):
+ flags = flags & _FLAGS["custom-colormap"]
+ colormapsize = 4 * 256 + 2;
+ colormapmode = im.palette.mode
+ colormap = im.getdata().getpalette()
+ else:
+ colormapsize = 0
+
+ if im.info.has_key("offset"):
+ offset = (rowbytes * rows + 16 + 3 + colormapsize) / 4;
+ else:
+ offset = 0
+
+ fp.write(o16b(cols) + o16b(rows) + o16b(rowbytes) + o16b(flags))
+ fp.write(chr(bpp))
+ fp.write(chr(version))
+ fp.write(o16b(offset))
+ fp.write(chr(transparent_index))
+ fp.write(chr(compression_type))
+ fp.write(o16b(0)) # reserved by Palm
+
+ # now write colormap if necessary
+
+ if colormapsize > 0:
+ fp.write(o16b(256))
+ for i in range(256):
+ fp.write(chr(i))
+ if colormapmode == 'RGB':
+ fp.write(chr(colormap[3 * i]) + chr(colormap[3 * i + 1]) + chr(colormap[3 * i + 2]))
+ elif colormapmode == 'RGBA':
+ fp.write(chr(colormap[4 * i]) + chr(colormap[4 * i + 1]) + chr(colormap[4 * i + 2]))
+
+ # now convert data to raw form
+ ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, rowbytes, 1))])
+
+ fp.flush()
+
+
+#
+# --------------------------------------------------------------------
+
+Image.register_save("Palm", _save)
+
+Image.register_extension("Palm", ".palm")
+
+Image.register_mime("Palm", "image/palm")
diff --git a/Imaging/PIL/PcdImagePlugin.py b/Imaging/PIL/PcdImagePlugin.py
new file mode 100644
index 0000000..957da24
--- /dev/null
+++ b/Imaging/PIL/PcdImagePlugin.py
@@ -0,0 +1,76 @@
+#
+# The Python Imaging Library.
+# $Id: PcdImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# PCD file handling
+#
+# History:
+# 96-05-10 fl Created
+# 96-05-27 fl Added draft mode (128x192, 256x384)
+#
+# Copyright (c) Secret Labs AB 1997.
+# Copyright (c) Fredrik Lundh 1996.
+#
+# See the README file for information on usage and redistribution.
+#
+
+
+__version__ = "0.1"
+
+
+import Image, ImageFile
+
+##
+# Image plugin for PhotoCD images. This plugin only reads the 768x512
+# image from the file; higher resolutions are encoded in a proprietary
+# encoding.
+
+class PcdImageFile(ImageFile.ImageFile):
+
+ format = "PCD"
+ format_description = "Kodak PhotoCD"
+
+ def _open(self):
+
+ # rough
+ self.fp.seek(2048)
+ s = self.fp.read(2048)
+
+ if s[:4] != "PCD_":
+ raise SyntaxError, "not a PCD file"
+
+ orientation = ord(s[1538]) & 3
+ if orientation == 1:
+ self.tile_post_rotate = 90 # hack
+ elif orientation == 3:
+ self.tile_post_rotate = -90
+
+ self.mode = "RGB"
+ self.size = 768, 512 # FIXME: not correct for rotated images!
+ self.tile = [("pcd", (0,0)+self.size, 96*2048, None)]
+
+ def draft(self, mode, size):
+
+ if len(self.tile) != 1:
+ return
+
+ d, e, o, a = self.tile[0]
+
+ if size:
+ scale = max(self.size[0] / size[0], self.size[1] / size[1])
+ for s, o in [(4,0*2048), (2,0*2048), (1,96*2048)]:
+ if scale >= s:
+ break
+ # e = e[0], e[1], (e[2]-e[0]+s-1)/s+e[0], (e[3]-e[1]+s-1)/s+e[1]
+ # self.size = ((self.size[0]+s-1)/s, (self.size[1]+s-1)/s)
+
+ self.tile = [(d, e, o, a)]
+
+ return self
+
+#
+# registry
+
+Image.register_open("PCD", PcdImageFile)
+
+Image.register_extension("PCD", ".pcd")
diff --git a/Imaging/PIL/PcfFontFile.py b/Imaging/PIL/PcfFontFile.py
new file mode 100644
index 0000000..9a689b2
--- /dev/null
+++ b/Imaging/PIL/PcfFontFile.py
@@ -0,0 +1,256 @@
+#
+# THIS IS WORK IN PROGRESS
+#
+# The Python Imaging Library
+# $Id: PcfFontFile.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# portable compiled font file parser
+#
+# history:
+# 1997-08-19 fl created
+# 2003-09-13 fl fixed loading of unicode fonts
+#
+# Copyright (c) 1997-2003 by Secret Labs AB.
+# Copyright (c) 1997-2003 by Fredrik Lundh.
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image
+import FontFile
+
+import string
+
+# --------------------------------------------------------------------
+# declarations
+
+PCF_MAGIC = 0x70636601 # "\x01fcp"
+
+PCF_PROPERTIES = (1<<0)
+PCF_ACCELERATORS = (1<<1)
+PCF_METRICS = (1<<2)
+PCF_BITMAPS = (1<<3)
+PCF_INK_METRICS = (1<<4)
+PCF_BDF_ENCODINGS = (1<<5)
+PCF_SWIDTHS = (1<<6)
+PCF_GLYPH_NAMES = (1<<7)
+PCF_BDF_ACCELERATORS = (1<<8)
+
+BYTES_PER_ROW = [
+ lambda bits: ((bits+7) >> 3),
+ lambda bits: ((bits+15) >> 3) & ~1,
+ lambda bits: ((bits+31) >> 3) & ~3,
+ lambda bits: ((bits+63) >> 3) & ~7,
+]
+
+
+def l16(c):
+ return ord(c[0]) + (ord(c[1])<<8)
+def l32(c):
+ return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
+
+def b16(c):
+ return ord(c[1]) + (ord(c[0])<<8)
+def b32(c):
+ return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
+
+def sz(s, o):
+ return s[o:string.index(s, "\0", o)]
+
+##
+# Font file plugin for the X11 PCF format.
+
+class PcfFontFile(FontFile.FontFile):
+
+ name = "name"
+
+ def __init__(self, fp):
+
+ magic = l32(fp.read(4))
+ if magic != PCF_MAGIC:
+ raise SyntaxError, "not a PCF file"
+
+ FontFile.FontFile.__init__(self)
+
+ count = l32(fp.read(4))
+ self.toc = {}
+ for i in range(count):
+ type = l32(fp.read(4))
+ self.toc[type] = l32(fp.read(4)), l32(fp.read(4)), l32(fp.read(4))
+
+ self.fp = fp
+
+ self.info = self._load_properties()
+
+ metrics = self._load_metrics()
+ bitmaps = self._load_bitmaps(metrics)
+ encoding = self._load_encoding()
+
+ #
+ # create glyph structure
+
+ for ch in range(256):
+ ix = encoding[ch]
+ if ix is not None:
+ x, y, l, r, w, a, d, f = metrics[ix]
+ glyph = (w, 0), (l, d-y, x+l, d), (0, 0, x, y), bitmaps[ix]
+ self.glyph[ch] = glyph
+
+ def _getformat(self, tag):
+
+ format, size, offset = self.toc[tag]
+
+ fp = self.fp
+ fp.seek(offset)
+
+ format = l32(fp.read(4))
+
+ if format & 4:
+ i16, i32 = b16, b32
+ else:
+ i16, i32 = l16, l32
+
+ return fp, format, i16, i32
+
+ def _load_properties(self):
+
+ #
+ # font properties
+
+ properties = {}
+
+ fp, format, i16, i32 = self._getformat(PCF_PROPERTIES)
+
+ nprops = i32(fp.read(4))
+
+ # read property description
+ p = []
+ for i in range(nprops):
+ p.append((i32(fp.read(4)), ord(fp.read(1)), i32(fp.read(4))))
+ if nprops & 3:
+ fp.seek(4 - (nprops & 3), 1) # pad
+
+ data = fp.read(i32(fp.read(4)))
+
+ for k, s, v in p:
+ k = sz(data, k)
+ if s:
+ v = sz(data, v)
+ properties[k] = v
+
+ return properties
+
+ def _load_metrics(self):
+
+ #
+ # font metrics
+
+ metrics = []
+
+ fp, format, i16, i32 = self._getformat(PCF_METRICS)
+
+ append = metrics.append
+
+ if (format & 0xff00) == 0x100:
+
+ # "compressed" metrics
+ for i in range(i16(fp.read(2))):
+ left = ord(fp.read(1)) - 128
+ right = ord(fp.read(1)) - 128
+ width = ord(fp.read(1)) - 128
+ ascent = ord(fp.read(1)) - 128
+ descent = ord(fp.read(1)) - 128
+ xsize = right - left
+ ysize = ascent + descent
+ append(
+ (xsize, ysize, left, right, width,
+ ascent, descent, 0)
+ )
+
+ else:
+
+ # "jumbo" metrics
+ for i in range(i32(fp.read(4))):
+ left = i16(fp.read(2))
+ right = i16(fp.read(2))
+ width = i16(fp.read(2))
+ ascent = i16(fp.read(2))
+ descent = i16(fp.read(2))
+ attributes = i16(fp.read(2))
+ xsize = right - left
+ ysize = ascent + descent
+ append(
+ (xsize, ysize, left, right, width,
+ ascent, descent, attributes)
+ )
+
+ return metrics
+
+ def _load_bitmaps(self, metrics):
+
+ #
+ # bitmap data
+
+ bitmaps = []
+
+ fp, format, i16, i32 = self._getformat(PCF_BITMAPS)
+
+ nbitmaps = i32(fp.read(4))
+
+ if nbitmaps != len(metrics):
+ raise IOError, "Wrong number of bitmaps"
+
+ offsets = []
+ for i in range(nbitmaps):
+ offsets.append(i32(fp.read(4)))
+
+ bitmapSizes = []
+ for i in range(4):
+ bitmapSizes.append(i32(fp.read(4)))
+
+ byteorder = format & 4 # non-zero => MSB
+ bitorder = format & 8 # non-zero => MSB
+ padindex = format & 3
+
+ bitmapsize = bitmapSizes[padindex]
+ offsets.append(bitmapsize)
+
+ data = fp.read(bitmapsize)
+
+ pad = BYTES_PER_ROW[padindex]
+ mode = "1;R"
+ if bitorder:
+ mode = "1"
+
+ for i in range(nbitmaps):
+ x, y, l, r, w, a, d, f = metrics[i]
+ b, e = offsets[i], offsets[i+1]
+ bitmaps.append(
+ Image.fromstring("1", (x, y), data[b:e], "raw", mode, pad(x))
+ )
+
+ return bitmaps
+
+ def _load_encoding(self):
+
+ # map character code to bitmap index
+ encoding = [None] * 256
+
+ fp, format, i16, i32 = self._getformat(PCF_BDF_ENCODINGS)
+
+ firstCol, lastCol = i16(fp.read(2)), i16(fp.read(2))
+ firstRow, lastRow = i16(fp.read(2)), i16(fp.read(2))
+
+ default = i16(fp.read(2))
+
+ nencoding = (lastCol - firstCol + 1) * (lastRow - firstRow + 1)
+
+ for i in range(nencoding):
+ encodingOffset = i16(fp.read(2))
+ if encodingOffset != 0xFFFF:
+ try:
+ encoding[i+firstCol] = encodingOffset
+ except IndexError:
+ break # only load ISO-8859-1 glyphs
+
+ return encoding
diff --git a/Imaging/PIL/PcxImagePlugin.py b/Imaging/PIL/PcxImagePlugin.py
new file mode 100644
index 0000000..8c0cd11
--- /dev/null
+++ b/Imaging/PIL/PcxImagePlugin.py
@@ -0,0 +1,167 @@
+#
+# The Python Imaging Library.
+# $Id: PcxImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# PCX file handling
+#
+# This format was originally used by ZSoft's popular PaintBrush
+# program for the IBM PC. It is also supported by many MS-DOS and
+# Windows applications, including the Windows PaintBrush program in
+# Windows 3.
+#
+# history:
+# 1995-09-01 fl Created
+# 1996-05-20 fl Fixed RGB support
+# 1997-01-03 fl Fixed 2-bit and 4-bit support
+# 1999-02-03 fl Fixed 8-bit support (broken in 1.0b1)
+# 1999-02-07 fl Added write support
+# 2002-06-09 fl Made 2-bit and 4-bit support a bit more robust
+# 2002-07-30 fl Seek from to current position, not beginning of file
+# 2003-06-03 fl Extract DPI settings (info["dpi"])
+#
+# Copyright (c) 1997-2003 by Secret Labs AB.
+# Copyright (c) 1995-2003 by Fredrik Lundh.
+#
+# See the README file for information on usage and redistribution.
+#
+
+__version__ = "0.6"
+
+import Image, ImageFile, ImagePalette
+
+def i16(c,o):
+ return ord(c[o]) + (ord(c[o+1])<<8)
+
+def _accept(prefix):
+ return ord(prefix[0]) == 10 and ord(prefix[1]) in [0, 2, 3, 5]
+
+##
+# Image plugin for Paintbrush images.
+
+class PcxImageFile(ImageFile.ImageFile):
+
+ format = "PCX"
+ format_description = "Paintbrush"
+
+ def _open(self):
+
+ # header
+ s = self.fp.read(128)
+ if not _accept(s):
+ raise SyntaxError, "not a PCX file"
+
+ # image
+ bbox = i16(s,4), i16(s,6), i16(s,8)+1, i16(s,10)+1
+ if bbox[2] <= bbox[0] or bbox[3] <= bbox[1]:
+ raise SyntaxError, "bad PCX image size"
+
+ # format
+ version = ord(s[1])
+ bits = ord(s[3])
+ planes = ord(s[65])
+ stride = i16(s,66)
+
+ self.info["dpi"] = i16(s,12), i16(s,14)
+
+ if bits == 1 and planes == 1:
+ mode = rawmode = "1"
+
+ elif bits == 1 and planes in (2, 4):
+ mode = "P"
+ rawmode = "P;%dL" % planes
+ self.palette = ImagePalette.raw("RGB", s[16:64])
+
+ elif version == 5 and bits == 8 and planes == 1:
+ mode = rawmode = "L"
+ # FIXME: hey, this doesn't work with the incremental loader !!!
+ self.fp.seek(-769, 2)
+ s = self.fp.read(769)
+ if len(s) == 769 and ord(s[0]) == 12:
+ # check if the palette is linear greyscale
+ for i in range(256):
+ if s[i*3+1:i*3+4] != chr(i)*3:
+ mode = rawmode = "P"
+ break
+ if mode == "P":
+ self.palette = ImagePalette.raw("RGB", s[1:])
+ self.fp.seek(128)
+
+ elif version == 5 and bits == 8 and planes == 3:
+ mode = "RGB"
+ rawmode = "RGB;L"
+
+ else:
+ raise IOError, "unknown PCX mode"
+
+ self.mode = mode
+ self.size = bbox[2]-bbox[0], bbox[3]-bbox[1]
+
+ bbox = (0, 0) + self.size
+
+ self.tile = [("pcx", bbox, self.fp.tell(), (rawmode, planes * stride))]
+
+# --------------------------------------------------------------------
+# save PCX files
+
+SAVE = {
+ # mode: (version, bits, planes, raw mode)
+ "1": (2, 1, 1, "1"),
+ "L": (5, 8, 1, "L"),
+ "P": (5, 8, 1, "P"),
+ "RGB": (5, 8, 3, "RGB;L"),
+}
+
+def o16(i):
+ return chr(i&255) + chr(i>>8&255)
+
+def _save(im, fp, filename, check=0):
+
+ try:
+ version, bits, planes, rawmode = SAVE[im.mode]
+ except KeyError:
+ raise ValueError, "Cannot save %s images as PCX" % im.mode
+
+ if check:
+ return check
+
+ # bytes per plane
+ stride = (im.size[0] * bits + 7) / 8
+
+ # under windows, we could determine the current screen size with
+ # "Image.core.display_mode()[1]", but I think that's overkill...
+
+ screen = im.size
+
+ dpi = 100, 100
+
+ # PCX header
+ fp.write(
+ chr(10) + chr(version) + chr(1) + chr(bits) + o16(0) +
+ o16(0) + o16(im.size[0]-1) + o16(im.size[1]-1) + o16(dpi[0]) +
+ o16(dpi[1]) + chr(0)*24 + chr(255)*24 + chr(0) + chr(planes) +
+ o16(stride) + o16(1) + o16(screen[0]) + o16(screen[1]) +
+ chr(0)*54
+ )
+
+ assert fp.tell() == 128
+
+ ImageFile._save(im, fp, [("pcx", (0,0)+im.size, 0,
+ (rawmode, bits*planes))])
+
+ if im.mode == "P":
+ # colour palette
+ fp.write(chr(12))
+ fp.write(im.im.getpalette("RGB", "RGB")) # 768 bytes
+ elif im.mode == "L":
+ # greyscale palette
+ fp.write(chr(12))
+ for i in range(256):
+ fp.write(chr(i)*3)
+
+# --------------------------------------------------------------------
+# registry
+
+Image.register_open("PCX", PcxImageFile, _accept)
+Image.register_save("PCX", _save)
+
+Image.register_extension("PCX", ".pcx")
diff --git a/Imaging/PIL/PdfImagePlugin.py b/Imaging/PIL/PdfImagePlugin.py
new file mode 100644
index 0000000..86567d6
--- /dev/null
+++ b/Imaging/PIL/PdfImagePlugin.py
@@ -0,0 +1,210 @@
+#
+# The Python Imaging Library.
+# $Id: PdfImagePlugin.py 2438 2005-05-25 21:09:48Z Fredrik $
+#
+# PDF (Acrobat) file handling
+#
+# History:
+# 1996-07-16 fl Created
+# 1997-01-18 fl Fixed header
+# 2004-02-21 fl Fixes for 1/L/CMYK images, etc.
+# 2004-02-24 fl Fixes for 1 and P images.
+#
+# Copyright (c) 1997-2004 by Secret Labs AB. All rights reserved.
+# Copyright (c) 1996-1997 by Fredrik Lundh.
+#
+# See the README file for information on usage and redistribution.
+#
+
+##
+# Image plugin for PDF images (output only).
+##
+
+__version__ = "0.4"
+
+import Image, ImageFile
+import StringIO
+
+
+#
+# --------------------------------------------------------------------
+
+# object ids:
+# 1. catalogue
+# 2. pages
+# 3. image
+# 4. page
+# 5. page contents
+
+def _obj(fp, obj, **dict):
+ fp.write("%d 0 obj\n" % obj)
+ if dict:
+ fp.write("<<\n")
+ for k, v in dict.items():
+ if v is not None:
+ fp.write("/%s %s\n" % (k, v))
+ fp.write(">>\n")
+
+def _endobj(fp):
+ fp.write("endobj\n")
+
+##
+# (Internal) Image save plugin for the PDF format.
+
+def _save(im, fp, filename):
+
+ #
+ # make sure image data is available
+ im.load()
+
+ xref = [0]*(5+1) # placeholders
+
+ fp.write("%PDF-1.2\n")
+ fp.write("% created by PIL PDF driver " + __version__ + "\n")
+
+ #
+ # Get image characteristics
+
+ width, height = im.size
+
+ # FIXME: Should replace ASCIIHexDecode with RunLengthDecode (packbits)
+ # or LZWDecode (tiff/lzw compression). Note that PDF 1.2 also supports
+ # Flatedecode (zip compression).
+
+ bits = 8
+ params = None
+
+ if im.mode == "1":
+ filter = "/ASCIIHexDecode"
+ colorspace = "/DeviceGray"
+ procset = "/ImageB" # grayscale
+ bits = 1
+ elif im.mode == "L":
+ filter = "/DCTDecode"
+ # params = "<< /Predictor 15 /Columns %d >>" % (width-2)
+ colorspace = "/DeviceGray"
+ procset = "/ImageB" # grayscale
+ elif im.mode == "P":
+ filter = "/ASCIIHexDecode"
+ colorspace = "[ /Indexed /DeviceRGB 255 <"
+ palette = im.im.getpalette("RGB")
+ for i in range(256):
+ r = ord(palette[i*3])
+ g = ord(palette[i*3+1])
+ b = ord(palette[i*3+2])
+ colorspace = colorspace + "%02x%02x%02x " % (r, g, b)
+ colorspace = colorspace + "> ]"
+ procset = "/ImageI" # indexed color
+ elif im.mode == "RGB":
+ filter = "/DCTDecode"
+ colorspace = "/DeviceRGB"
+ procset = "/ImageC" # color images
+ elif im.mode == "CMYK":
+ filter = "/DCTDecode"
+ colorspace = "/DeviceCMYK"
+ procset = "/ImageC" # color images
+ else:
+ raise ValueError("cannot save mode %s" % im.mode)
+
+ #
+ # catalogue
+
+ xref[1] = fp.tell()
+ _obj(fp, 1, Type = "/Catalog",
+ Pages = "2 0 R")
+ _endobj(fp)
+
+ #
+ # pages
+
+ xref[2] = fp.tell()
+ _obj(fp, 2, Type = "/Pages",
+ Count = 1,
+ Kids = "[4 0 R]")
+ _endobj(fp)
+
+ #
+ # image
+
+ op = StringIO.StringIO()
+
+ if filter == "/ASCIIHexDecode":
+ if bits == 1:
+ # FIXME: the hex encoder doesn't support packed 1-bit
+ # images; do things the hard way...
+ data = im.tostring("raw", "1")
+ im = Image.new("L", (len(data), 1), None)
+ im.putdata(data)
+ ImageFile._save(im, op, [("hex", (0,0)+im.size, 0, im.mode)])
+ elif filter == "/DCTDecode":
+ ImageFile._save(im, op, [("jpeg", (0,0)+im.size, 0, im.mode)])
+ elif filter == "/FlateDecode":
+ ImageFile._save(im, op, [("zip", (0,0)+im.size, 0, im.mode)])
+ elif filter == "/RunLengthDecode":
+ ImageFile._save(im, op, [("packbits", (0,0)+im.size, 0, im.mode)])
+ else:
+ raise ValueError("unsupported PDF filter (%s)" % filter)
+
+ xref[3] = fp.tell()
+ _obj(fp, 3, Type = "/XObject",
+ Subtype = "/Image",
+ Width = width,
+ Height = height,
+ Length = len(op.getvalue()),
+ Filter = filter,
+ BitsPerComponent = bits,
+ DecodeParams = params,
+ ColorSpace = colorspace)
+
+ fp.write("stream\n")
+ fp.write(op.getvalue())
+ fp.write("\nendstream\n")
+
+ _endobj(fp)
+
+ #
+ # page
+
+ xref[4] = fp.tell()
+ _obj(fp, 4)
+ fp.write("<<\n/Type /Page\n/Parent 2 0 R\n"\
+ "/Resources <<\n/ProcSet [ /PDF %s ]\n"\
+ "/XObject << /image 3 0 R >>\n>>\n"\
+ "/MediaBox [ 0 0 %d %d ]\n/Contents 5 0 R\n>>\n" %\
+ (procset, width, height))
+ _endobj(fp)
+
+ #
+ # page contents
+
+ op = StringIO.StringIO()
+
+ op.write("q %d 0 0 %d 0 0 cm /image Do Q\n" % (width, height))
+
+ xref[5] = fp.tell()
+ _obj(fp, 5, Length = len(op.getvalue()))
+
+ fp.write("stream\n")
+ fp.write(op.getvalue())
+ fp.write("\nendstream\n")
+
+ _endobj(fp)
+
+ #
+ # trailer
+ startxref = fp.tell()
+ fp.write("xref\n0 %d\n0000000000 65535 f \n" % len(xref))
+ for x in xref[1:]:
+ fp.write("%010d 00000 n \n" % x)
+ fp.write("trailer\n<<\n/Size %d\n/Root 1 0 R\n>>\n" % len(xref))
+ fp.write("startxref\n%d\n%%%%EOF\n" % startxref)
+ fp.flush()
+
+#
+# --------------------------------------------------------------------
+
+Image.register_save("PDF", _save)
+
+Image.register_extension("PDF", ".pdf")
+
+Image.register_mime("PDF", "application/pdf")
diff --git a/Imaging/PIL/PixarImagePlugin.py b/Imaging/PIL/PixarImagePlugin.py
new file mode 100644
index 0000000..d4b136f
--- /dev/null
+++ b/Imaging/PIL/PixarImagePlugin.py
@@ -0,0 +1,71 @@
+#
+# The Python Imaging Library.
+# $Id: PixarImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# PIXAR raster support for PIL
+#
+# history:
+# 97-01-29 fl Created
+#
+# notes:
+# This is incomplete; it is based on a few samples created with
+# Photoshop 2.5 and 3.0, and a summary description provided by
+# Greg Coats <gcoats@labiris.er.usgs.gov>. Hopefully, "L" and
+# "RGBA" support will be added in future versions.
+#
+# Copyright (c) Secret Labs AB 1997.
+# Copyright (c) Fredrik Lundh 1997.
+#
+# See the README file for information on usage and redistribution.
+#
+
+__version__ = "0.1"
+
+import Image, ImageFile
+
+#
+# helpers
+
+def i16(c):
+ return ord(c[0]) + (ord(c[1])<<8)
+
+def i32(c):
+ return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
+
+##
+# Image plugin for PIXAR raster images.
+
+class PixarImageFile(ImageFile.ImageFile):
+
+ format = "PIXAR"
+ format_description = "PIXAR raster image"
+
+ def _open(self):
+
+ # assuming a 4-byte magic label (FIXME: add "_accept" hook)
+ s = self.fp.read(4)
+ if s != "\200\350\000\000":
+ raise SyntaxError, "not a PIXAR file"
+
+ # read rest of header
+ s = s + self.fp.read(508)
+
+ self.size = i16(s[418:420]), i16(s[416:418])
+
+ # get channel/depth descriptions
+ mode = i16(s[424:426]), i16(s[426:428])
+
+ if mode == (14, 2):
+ self.mode = "RGB"
+ # FIXME: to be continued...
+
+ # create tile descriptor (assuming "dumped")
+ self.tile = [("raw", (0,0)+self.size, 1024, (self.mode, 0, 1))]
+
+#
+# --------------------------------------------------------------------
+
+Image.register_open("PIXAR", PixarImageFile)
+
+#
+# FIXME: what's the standard extension?
diff --git a/Imaging/PIL/PngImagePlugin.py b/Imaging/PIL/PngImagePlugin.py
new file mode 100644
index 0000000..0e8ce9f
--- /dev/null
+++ b/Imaging/PIL/PngImagePlugin.py
@@ -0,0 +1,558 @@
+#
+# The Python Imaging Library.
+# $Id: PngImagePlugin.py 2203 2004-12-19 14:32:32Z fredrik $
+#
+# PNG support code
+#
+# See "PNG (Portable Network Graphics) Specification, version 1.0;
+# W3C Recommendation", 1996-10-01, Thomas Boutell (ed.).
+#
+# history:
+# 1996-05-06 fl Created (couldn't resist it)
+# 1996-12-14 fl Upgraded, added read and verify support (0.2)
+# 1996-12-15 fl Separate PNG stream parser
+# 1996-12-29 fl Added write support, added getchunks
+# 1996-12-30 fl Eliminated circular references in decoder (0.3)
+# 1998-07-12 fl Read/write 16-bit images as mode I (0.4)
+# 2001-02-08 fl Added transparency support (from Zircon) (0.5)
+# 2001-04-16 fl Don't close data source in "open" method (0.6)
+# 2004-02-24 fl Don't even pretend to support interlaced files (0.7)
+# 2004-08-31 fl Do basic sanity check on chunk identifiers (0.8)
+# 2004-09-20 fl Added PngInfo chunk container
+# 2004-12-18 fl Added DPI read support (based on code by Niki Spahiev)
+#
+# Copyright (c) 1997-2004 by Secret Labs AB
+# Copyright (c) 1996 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+__version__ = "0.8.2"
+
+import re, string
+
+import Image, ImageFile, ImagePalette
+
+
+def i16(c):
+ return ord(c[1]) + (ord(c[0])<<8)
+def i32(c):
+ return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
+
+is_cid = re.compile("\w\w\w\w").match
+
+
+_MAGIC = "\211PNG\r\n\032\n"
+
+
+_MODES = {
+ # supported bits/color combinations, and corresponding modes/rawmodes
+ (1, 0): ("1", "1"),
+ (2, 0): ("L", "L;2"),
+ (4, 0): ("L", "L;4"),
+ (8, 0): ("L", "L"),
+ (16,0): ("I", "I;16B"),
+ (8, 2): ("RGB", "RGB"),
+ (16,2): ("RGB", "RGB;16B"),
+ (1, 3): ("P", "P;1"),
+ (2, 3): ("P", "P;2"),
+ (4, 3): ("P", "P;4"),
+ (8, 3): ("P", "P"),
+ (8, 4): ("LA", "LA"),
+ (16,4): ("RGBA", "LA;16B"), # LA;16B->LA not yet available
+ (8, 6): ("RGBA", "RGBA"),
+ (16,6): ("RGBA", "RGBA;16B"),
+}
+
+
+# --------------------------------------------------------------------
+# Support classes. Suitable for PNG and related formats like MNG etc.
+
+class ChunkStream:
+
+ def __init__(self, fp):
+
+ self.fp = fp
+ self.queue = []
+
+ if not hasattr(Image.core, "crc32"):
+ self.crc = self.crc_skip
+
+ def read(self):
+ "Fetch a new chunk. Returns header information."
+
+ if self.queue:
+ cid, pos, len = self.queue[-1]
+ del self.queue[-1]
+ self.fp.seek(pos)
+ else:
+ s = self.fp.read(8)
+ cid = s[4:]
+ pos = self.fp.tell()
+ len = i32(s)
+
+ if not is_cid(cid):
+ raise SyntaxError, "broken PNG file (chunk %s)" % repr(cid)
+
+ return cid, pos, len
+
+ def close(self):
+ self.queue = self.crc = self.fp = None
+
+ def push(self, cid, pos, len):
+
+ self.queue.append((cid, pos, len))
+
+ def call(self, cid, pos, len):
+ "Call the appropriate chunk handler"
+
+ if Image.DEBUG:
+ print "STREAM", cid, pos, len
+ return getattr(self, "chunk_" + cid)(pos, len)
+
+ def crc(self, cid, data):
+ "Read and verify checksum"
+
+ crc1 = Image.core.crc32(data, Image.core.crc32(cid))
+ crc2 = i16(self.fp.read(2)), i16(self.fp.read(2))
+ if crc1 != crc2:
+ raise SyntaxError, "broken PNG file"\
+ "(bad header checksum in %s)" % cid
+
+ def crc_skip(self, cid, data):
+ "Read checksum. Used if the C module is not present"
+
+ self.fp.read(4)
+
+ def verify(self, endchunk = "IEND"):
+
+ # Simple approach; just calculate checksum for all remaining
+ # blocks. Must be called directly after open.
+
+ cids = []
+
+ while 1:
+ cid, pos, len = self.read()
+ if cid == endchunk:
+ break
+ self.crc(cid, ImageFile._safe_read(self.fp, len))
+ cids.append(cid)
+
+ return cids
+
+
+# --------------------------------------------------------------------
+# PNG chunk container (for use with save(pnginfo=))
+
+class PngInfo:
+
+ def __init__(self):
+ self.chunks = []
+
+ def add(self, cid, data):
+ self.chunks.append((cid, data))
+
+ def add_text(self, key, value, zip=0):
+ if zip:
+ import zlib
+ self.add("zTXt", key + "\0\0" + zlib.compress(value))
+ else:
+ self.add("tEXt", key + "\0" + value)
+
+# --------------------------------------------------------------------
+# PNG image stream (IHDR/IEND)
+
+class PngStream(ChunkStream):
+
+ def __init__(self, fp):
+
+ ChunkStream.__init__(self, fp)
+
+ # local copies of Image attributes
+ self.im_info = {}
+ self.im_size = (0,0)
+ self.im_mode = None
+ self.im_tile = None
+ self.im_palette = None
+
+ def chunk_IHDR(self, pos, len):
+
+ # image header
+ s = ImageFile._safe_read(self.fp, len)
+ self.im_size = i32(s), i32(s[4:])
+ try:
+ self.im_mode, self.im_rawmode = _MODES[(ord(s[8]), ord(s[9]))]
+ except:
+ pass
+ if ord(s[12]):
+ self.im_info["interlace"] = 1
+ if ord(s[11]):
+ raise SyntaxError, "unknown filter category"
+ return s
+
+ def chunk_IDAT(self, pos, len):
+
+ # image data
+ self.im_tile = [("zip", (0,0)+self.im_size, pos, self.im_rawmode)]
+ self.im_idat = len
+ raise EOFError
+
+ def chunk_IEND(self, pos, len):
+
+ # end of PNG image
+ raise EOFError
+
+ def chunk_PLTE(self, pos, len):
+
+ # palette
+ s = ImageFile._safe_read(self.fp, len)
+ if self.im_mode == "P":
+ self.im_palette = "RGB", s
+ return s
+
+ def chunk_tRNS(self, pos, len):
+
+ # transparency
+ s = ImageFile._safe_read(self.fp, len)
+ if self.im_mode == "P":
+ i = string.find(s, chr(0))
+ if i >= 0:
+ self.im_info["transparency"] = i
+ elif self.im_mode == "L":
+ self.im_info["transparency"] = i16(s)
+ return s
+
+ def chunk_gAMA(self, pos, len):
+
+ # gamma setting
+ s = ImageFile._safe_read(self.fp, len)
+ self.im_info["gamma"] = i32(s) / 100000.0
+ return s
+
+ def chunk_pHYs(self, pos, len):
+
+ # pixels per unit
+ s = ImageFile._safe_read(self.fp, len)
+ px, py = i32(s), i32(s[4:])
+ unit = ord(s[8])
+ if unit == 1: # meter
+ dpi = int(px * 0.0254 + 0.5), int(py * 0.0254 + 0.5)
+ self.im_info["dpi"] = dpi
+ elif unit == 0:
+ self.im_info["aspect"] = px, py
+ return s
+
+ def chunk_tEXt(self, pos, len):
+
+ # text
+ s = ImageFile._safe_read(self.fp, len)
+ try:
+ k, v = string.split(s, "\0", 1)
+ except ValueError:
+ k = s; v = "" # fallback for broken tEXt tags
+ if k:
+ self.im_info[k] = v
+ return s
+
+
+# --------------------------------------------------------------------
+# PNG reader
+
+def _accept(prefix):
+ return prefix[:8] == _MAGIC
+
+##
+# Image plugin for PNG images.
+
+class PngImageFile(ImageFile.ImageFile):
+
+ format = "PNG"
+ format_description = "Portable network graphics"
+
+ def _open(self):
+
+ if self.fp.read(8) != _MAGIC:
+ raise SyntaxError, "not a PNG file"
+
+ #
+ # Parse headers up to the first IDAT chunk
+
+ self.png = PngStream(self.fp)
+
+ while 1:
+
+ #
+ # get next chunk
+
+ cid, pos, len = self.png.read()
+
+ try:
+ s = self.png.call(cid, pos, len)
+ except EOFError:
+ break
+ except AttributeError:
+ if Image.DEBUG:
+ print cid, pos, len, "(unknown)"
+ s = ImageFile._safe_read(self.fp, len)
+
+ self.png.crc(cid, s)
+
+ #
+ # Copy relevant attributes from the PngStream. An alternative
+ # would be to let the PngStream class modify these attributes
+ # directly, but that introduces circular references which are
+ # difficult to break if things go wrong in the decoder...
+ # (believe me, I've tried ;-)
+
+ self.mode = self.png.im_mode
+ self.size = self.png.im_size
+ self.info = self.png.im_info
+ self.tile = self.png.im_tile
+
+ if self.png.im_palette:
+ rawmode, data = self.png.im_palette
+ self.palette = ImagePalette.raw(rawmode, data)
+
+ self.__idat = len # used by load_read()
+
+
+ def verify(self):
+ "Verify PNG file"
+
+ if self.fp is None:
+ raise RuntimeError("verify must be called directly after open")
+
+ # back up to beginning of IDAT block
+ self.fp.seek(self.tile[0][2] - 8)
+
+ self.png.verify()
+ self.png.close()
+
+ self.fp = None
+
+ def load_prepare(self):
+ "internal: prepare to read PNG file"
+
+ if self.info.get("interlace"):
+ raise IOError("cannot read interlaced PNG files")
+
+ ImageFile.ImageFile.load_prepare(self)
+
+ def load_read(self, bytes):
+ "internal: read more image data"
+
+ while self.__idat == 0:
+ # end of chunk, skip forward to next one
+
+ self.fp.read(4) # CRC
+
+ cid, pos, len = self.png.read()
+
+ if cid not in ["IDAT", "DDAT"]:
+ self.png.push(cid, pos, len)
+ return ""
+
+ self.__idat = len # empty chunks are allowed
+
+ # read more data from this chunk
+ if bytes <= 0:
+ bytes = self.__idat
+ else:
+ bytes = min(bytes, self.__idat)
+
+ self.__idat = self.__idat - bytes
+
+ return self.fp.read(bytes)
+
+
+ def load_end(self):
+ "internal: finished reading image data"
+
+ self.png.close()
+ self.png = None
+
+
+# --------------------------------------------------------------------
+# PNG writer
+
+def o16(i):
+ return chr(i>>8&255) + chr(i&255)
+
+def o32(i):
+ return chr(i>>24&255) + chr(i>>16&255) + chr(i>>8&255) + chr(i&255)
+
+_OUTMODES = {
+ # supported PIL modes, and corresponding rawmodes/bits/color combinations
+ "1": ("1", chr(1)+chr(0)),
+ "L;1": ("L;1", chr(1)+chr(0)),
+ "L;2": ("L;2", chr(2)+chr(0)),
+ "L;4": ("L;4", chr(4)+chr(0)),
+ "L": ("L", chr(8)+chr(0)),
+ "LA": ("LA", chr(8)+chr(4)),
+ "I": ("I;16B", chr(16)+chr(0)),
+ "P;1": ("P;1", chr(1)+chr(3)),
+ "P;2": ("P;2", chr(2)+chr(3)),
+ "P;4": ("P;4", chr(4)+chr(3)),
+ "P": ("P", chr(8)+chr(3)),
+ "RGB": ("RGB", chr(8)+chr(2)),
+ "RGBA":("RGBA", chr(8)+chr(6)),
+}
+
+def putchunk(fp, cid, *data):
+ "Write a PNG chunk (including CRC field)"
+
+ data = string.join(data, "")
+
+ fp.write(o32(len(data)) + cid)
+ fp.write(data)
+ hi, lo = Image.core.crc32(data, Image.core.crc32(cid))
+ fp.write(o16(hi) + o16(lo))
+
+class _idat:
+ # wrap output from the encoder in IDAT chunks
+
+ def __init__(self, fp, chunk):
+ self.fp = fp
+ self.chunk = chunk
+ def write(self, data):
+ self.chunk(self.fp, "IDAT", data)
+
+def _save(im, fp, filename, chunk=putchunk, check=0):
+ # save an image to disk (called by the save method)
+
+ mode = im.mode
+
+ if mode == "P":
+
+ #
+ # attempt to minimize storage requirements for palette images
+
+ if im.encoderinfo.has_key("bits"):
+
+ # number of bits specified by user
+ n = 1 << im.encoderinfo["bits"]
+
+ else:
+
+ # check palette contents
+ n = 256 # FIXME
+
+ if n <= 2:
+ bits = 1
+ elif n <= 4:
+ bits = 2
+ elif n <= 16:
+ bits = 4
+ else:
+ bits = 8
+
+ if bits != 8:
+ mode = "%s;%d" % (mode, bits)
+
+ # encoder options
+ if im.encoderinfo.has_key("dictionary"):
+ dictionary = im.encoderinfo["dictionary"]
+ else:
+ dictionary = ""
+
+ im.encoderconfig = (im.encoderinfo.has_key("optimize"), dictionary)
+
+ # get the corresponding PNG mode
+ try:
+ rawmode, mode = _OUTMODES[mode]
+ except KeyError:
+ raise IOError, "cannot write mode %s as PNG" % mode
+
+ if check:
+ return check
+
+ #
+ # write minimal PNG file
+
+ fp.write(_MAGIC)
+
+ chunk(fp, "IHDR",
+ o32(im.size[0]), o32(im.size[1]), # 0: size
+ mode, # 8: depth/type
+ chr(0), # 10: compression
+ chr(0), # 11: filter category
+ chr(0)) # 12: interlace flag
+
+ if im.mode == "P":
+ chunk(fp, "PLTE", im.im.getpalette("RGB"))
+
+ if im.encoderinfo.has_key("transparency"):
+ if im.mode == "P":
+ transparency = max(0, min(255, im.encoderinfo["transparency"]))
+ chunk(fp, "tRNS", chr(255) * transparency + chr(0))
+ elif im.mode == "L":
+ transparency = max(0, min(65535, im.encoderinfo["transparency"]))
+ chunk(fp, "tRNS", o16(transparency))
+ else:
+ raise IOError, "cannot use transparency for this mode"
+
+ if 0:
+ # FIXME: to be supported some day
+ chunk(fp, "gAMA", o32(int(gamma * 100000.0)))
+
+ dpi = im.encoderinfo.get("dpi")
+ if dpi:
+ chunk(fp, "pHYs",
+ o32(int(dpi[0] / 0.0254 + 0.5)),
+ o32(int(dpi[1] / 0.0254 + 0.5)),
+ chr(1))
+
+ info = im.encoderinfo.get("pnginfo")
+ if info:
+ for cid, data in info.chunks:
+ chunk(fp, cid, data)
+
+ ImageFile._save(im, _idat(fp, chunk), [("zip", (0,0)+im.size, 0, rawmode)])
+
+ chunk(fp, "IEND", "")
+
+ try:
+ fp.flush()
+ except:
+ pass
+
+
+# --------------------------------------------------------------------
+# PNG chunk converter
+
+def getchunks(im, **params):
+ """Return a list of PNG chunks representing this image."""
+
+ class collector:
+ data = []
+ def write(self, data):
+ pass
+ def append(self, chunk):
+ self.data.append(chunk)
+
+ def append(fp, cid, *data):
+ data = string.join(data, "")
+ hi, lo = Image.core.crc32(data, Image.core.crc32(cid))
+ crc = o16(hi) + o16(lo)
+ fp.append((cid, data, crc))
+
+ fp = collector()
+
+ try:
+ im.encoderinfo = params
+ _save(im, fp, None, append)
+ finally:
+ del im.encoderinfo
+
+ return fp.data
+
+
+# --------------------------------------------------------------------
+# Registry
+
+Image.register_open("PNG", PngImageFile, _accept)
+Image.register_save("PNG", _save)
+
+Image.register_extension("PNG", ".png")
+
+Image.register_mime("PNG", "image/png")
diff --git a/Imaging/PIL/PpmImagePlugin.py b/Imaging/PIL/PpmImagePlugin.py
new file mode 100644
index 0000000..b9b9f81
--- /dev/null
+++ b/Imaging/PIL/PpmImagePlugin.py
@@ -0,0 +1,131 @@
+#
+# The Python Imaging Library.
+# $Id: PpmImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# PPM support for PIL
+#
+# History:
+# 96-03-24 fl Created
+# 98-03-06 fl Write RGBA images (as RGB, that is)
+#
+# Copyright (c) Secret Labs AB 1997-98.
+# Copyright (c) Fredrik Lundh 1996.
+#
+# See the README file for information on usage and redistribution.
+#
+
+
+__version__ = "0.2"
+
+import string
+
+import Image, ImageFile
+
+#
+# --------------------------------------------------------------------
+
+MODES = {
+ # standard
+ "P4": "1",
+ "P5": "L",
+ "P6": "RGB",
+ # extensions
+ "P0CMYK": "CMYK",
+ # PIL extensions (for test purposes only)
+ "PyP": "P",
+ "PyRGBA": "RGBA",
+ "PyCMYK": "CMYK"
+}
+
+def _accept(prefix):
+ return prefix[0] == "P" and prefix[1] in "0456y"
+
+##
+# Image plugin for PBM, PGM, and PPM images.
+
+class PpmImageFile(ImageFile.ImageFile):
+
+ format = "PPM"
+ format_description = "Pbmplus image"
+
+ def _token(self, s = ""):
+ while 1: # read until next whitespace
+ c = self.fp.read(1)
+ if not c or c in string.whitespace:
+ break
+ s = s + c
+ return s
+
+ def _open(self):
+
+ # check magic
+ s = self.fp.read(1)
+ if s != "P":
+ raise SyntaxError, "not a PPM file"
+ mode = MODES[self._token(s)]
+
+ if mode == "1":
+ self.mode = "1"
+ rawmode = "1;I"
+ else:
+ self.mode = rawmode = mode
+
+ for ix in range(3):
+ while 1:
+ while 1:
+ s = self.fp.read(1)
+ if s not in string.whitespace:
+ break
+ if s != "#":
+ break
+ s = self.fp.readline()
+ s = int(self._token(s))
+ if ix == 0:
+ xsize = s
+ elif ix == 1:
+ ysize = s
+ if mode == "1":
+ break
+
+ self.size = xsize, ysize
+ self.tile = [("raw",
+ (0, 0, xsize, ysize),
+ self.fp.tell(),
+ (rawmode, 0, 1))]
+
+ # ALTERNATIVE: load via builtin debug function
+ # self.im = Image.core.open_ppm(self.filename)
+ # self.mode = self.im.mode
+ # self.size = self.im.size
+
+#
+# --------------------------------------------------------------------
+
+def _save(im, fp, filename):
+ if im.mode == "1":
+ rawmode, head = "1;I", "P4"
+ elif im.mode == "L":
+ rawmode, head = "L", "P5"
+ elif im.mode == "RGB":
+ rawmode, head = "RGB", "P6"
+ elif im.mode == "RGBA":
+ rawmode, head = "RGB", "P6"
+ else:
+ raise IOError, "cannot write mode %s as PPM" % im.mode
+ fp.write(head + "\n%d %d\n" % im.size)
+ if head != "P4":
+ fp.write("255\n")
+ ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, 0, 1))])
+
+ # ALTERNATIVE: save via builtin debug function
+ # im._dump(filename)
+
+#
+# --------------------------------------------------------------------
+
+Image.register_open("PPM", PpmImageFile, _accept)
+Image.register_save("PPM", _save)
+
+Image.register_extension("PPM", ".pbm")
+Image.register_extension("PPM", ".pgm")
+Image.register_extension("PPM", ".ppm")
diff --git a/Imaging/PIL/PsdImagePlugin.py b/Imaging/PIL/PsdImagePlugin.py
new file mode 100644
index 0000000..1e68c0d
--- /dev/null
+++ b/Imaging/PIL/PsdImagePlugin.py
@@ -0,0 +1,271 @@
+#
+# The Python Imaging Library
+# $Id: PsdImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# Adobe PSD 2.5/3.0 file handling
+#
+# History:
+# 1995-09-01 fl Created
+# 1997-01-03 fl Read most PSD images
+# 1997-01-18 fl Fixed P and CMYK support
+# 2001-10-21 fl Added seek/tell support (for layers)
+#
+# Copyright (c) 1997-2001 by Secret Labs AB.
+# Copyright (c) 1995-2001 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+__version__ = "0.4"
+
+import string
+import Image, ImageFile, ImagePalette
+
+MODES = {
+ # (photoshop mode, bits) -> (pil mode, required channels)
+ (0, 1): ("1", 1),
+ (0, 8): ("L", 1),
+ (1, 8): ("L", 1),
+ (2, 8): ("P", 1),
+ (3, 8): ("RGB", 3),
+ (4, 8): ("CMYK", 4),
+ (7, 8): ("L", 1), # FIXME: multilayer
+ (8, 8): ("L", 1), # duotone
+ (9, 8): ("LAB", 3)
+}
+
+#
+# helpers
+
+def i16(c):
+ return ord(c[1]) + (ord(c[0])<<8)
+
+def i32(c):
+ return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
+
+# --------------------------------------------------------------------.
+# read PSD images
+
+def _accept(prefix):
+ return prefix[:4] == "8BPS"
+
+##
+# Image plugin for Photoshop images.
+
+class PsdImageFile(ImageFile.ImageFile):
+
+ format = "PSD"
+ format_description = "Adobe Photoshop"
+
+ def _open(self):
+
+ read = self.fp.read
+
+ #
+ # header
+
+ s = read(26)
+ if s[:4] != "8BPS" or i16(s[4:]) != 1:
+ raise SyntaxError, "not a PSD file"
+
+ psd_bits = i16(s[22:])
+ psd_channels = i16(s[12:])
+ psd_mode = i16(s[24:])
+
+ mode, channels = MODES[(psd_mode, psd_bits)]
+
+ if channels > psd_channels:
+ raise IOError, "not enough channels"
+
+ self.mode = mode
+ self.size = i32(s[18:]), i32(s[14:])
+
+ #
+ # color mode data
+
+ size = i32(read(4))
+ if size:
+ data = read(size)
+ if mode == "P" and size == 768:
+ self.palette = ImagePalette.raw("RGB;L", data)
+
+ #
+ # image resources
+
+ self.resources = []
+
+ size = i32(read(4))
+ if size:
+ # load resources
+ end = self.fp.tell() + size
+ while self.fp.tell() < end:
+ signature = read(4)
+ id = i16(read(2))
+ name = read(ord(read(1)))
+ if not (len(name) & 1):
+ read(1) # padding
+ data = read(i32(read(4)))
+ if (len(data) & 1):
+ read(1) # padding
+ self.resources.append((id, name, data))
+
+ #
+ # layer and mask information
+
+ self.layers = []
+
+ size = i32(read(4))
+ if size:
+ end = self.fp.tell() + size
+ size = i32(read(4))
+ if size:
+ self.layers = _layerinfo(self.fp)
+ self.fp.seek(end)
+
+ #
+ # image descriptor
+
+ self.tile = _maketile(self.fp, mode, (0, 0) + self.size, channels)
+
+ # keep the file open
+ self._fp = self.fp
+ self.frame = 0
+
+ def seek(self, layer):
+ # seek to given layer (1..max)
+ if layer == self.frame:
+ return
+ try:
+ if layer <= 0:
+ raise IndexError
+ name, mode, bbox, tile = self.layers[layer-1]
+ self.mode = mode
+ self.tile = tile
+ self.frame = layer
+ self.fp = self._fp
+ return name, bbox
+ except IndexError:
+ raise EOFError, "no such layer"
+
+ def tell(self):
+ # return layer number (0=image, 1..max=layers)
+ return self.frame
+
+ def load_prepare(self):
+ # create image memory if necessary
+ if not self.im or\
+ self.im.mode != self.mode or self.im.size != self.size:
+ self.im = Image.core.fill(self.mode, self.size, 0)
+ # create palette (optional)
+ if self.mode == "P":
+ Image.Image.load(self)
+
+def _layerinfo(file):
+ # read layerinfo block
+ layers = []
+ read = file.read
+
+ for i in range(abs(i16(read(2)))):
+
+ # bounding box
+ y0 = i32(read(4)); x0 = i32(read(4))
+ y1 = i32(read(4)); x1 = i32(read(4))
+
+ # image info
+ info = []
+ mode = []
+ for i in range(i16(read(2))):
+ type = i16(read(2))
+ if type == 65535:
+ m = "A"
+ else:
+ m = "RGB"[type]
+ mode.append(m)
+ size = i32(read(4))
+ info.append((m, size))
+
+ # figure out the image mode
+ mode.sort()
+ if mode == ["R"]:
+ mode = "L"
+ elif mode == ["B", "G", "R"]:
+ mode = "RGB"
+ elif mode == ["A", "B", "G", "R"]:
+ mode = "RGBA"
+ else:
+ mode = None # unknown
+
+ # skip over blend flags and extra information
+ filler = read(12)
+ name = None # FIXME
+ file.seek(i32(read(4)), 1)
+
+ layers.append((name, mode, (x0, y0, x1, y1)))
+
+ # get tiles
+ i = 0
+ for name, mode, bbox in layers:
+ tile = []
+ for m in mode:
+ t = _maketile(file, m, bbox, 1)
+ if t:
+ tile.extend(t)
+ layers[i] = name, mode, bbox, tile
+ i = i + 1
+
+ return layers
+
+def _maketile(file, mode, bbox, channels):
+
+ tile = None
+ read = file.read
+
+ compression = i16(read(2))
+
+ xsize = bbox[2] - bbox[0]
+ ysize = bbox[3] - bbox[1]
+
+ offset = file.tell()
+
+ if compression == 0:
+ #
+ # raw compression
+ tile = []
+ for channel in range(channels):
+ layer = mode[channel]
+ if mode == "CMYK":
+ layer = layer + ";I"
+ tile.append(("raw", bbox, offset, layer))
+ offset = offset + xsize*ysize
+
+ elif compression == 1:
+ #
+ # packbits compression
+ i = 0
+ tile = []
+ bytecount = read(channels * ysize * 2)
+ offset = file.tell()
+ for channel in range(channels):
+ layer = mode[channel]
+ if mode == "CMYK":
+ layer = layer + ";I"
+ tile.append(
+ ("packbits", bbox, offset, layer)
+ )
+ for y in range(ysize):
+ offset = offset + i16(bytecount[i:i+2])
+ i = i + 2
+
+ file.seek(offset)
+
+ if offset & 1:
+ read(1) # padding
+
+ return tile
+
+# --------------------------------------------------------------------
+# registry
+
+Image.register_open("PSD", PsdImageFile, _accept)
+
+Image.register_extension("PSD", ".psd")
diff --git a/Imaging/PIL/SgiImagePlugin.py b/Imaging/PIL/SgiImagePlugin.py
new file mode 100644
index 0000000..0ab741e
--- /dev/null
+++ b/Imaging/PIL/SgiImagePlugin.py
@@ -0,0 +1,91 @@
+#
+# The Python Imaging Library.
+# $Id: SgiImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# SGI image file handling
+#
+# See "The SGI Image File Format (Draft version 0.97)", Paul Haeberli.
+# <ftp://ftp.sgi.com/graphics/SGIIMAGESPEC>
+#
+# History:
+# 1995-09-10 fl Created
+#
+# Copyright (c) Secret Labs AB 1997.
+# Copyright (c) Fredrik Lundh 1995.
+#
+# See the README file for information on usage and redistribution.
+#
+
+
+__version__ = "0.1"
+
+
+import string
+import Image, ImageFile
+
+
+def i16(c):
+ return ord(c[1]) + (ord(c[0])<<8)
+
+def i32(c):
+ return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
+
+
+def _accept(prefix):
+ return i16(prefix) == 474
+
+##
+# Image plugin for SGI images.
+
+class SgiImageFile(ImageFile.ImageFile):
+
+ format = "SGI"
+ format_description = "SGI Image File Format"
+
+ def _open(self):
+
+ # HEAD
+ s = self.fp.read(512)
+ if i16(s) != 474:
+ raise SyntaxError, "not an SGI image file"
+
+ # relevant header entries
+ compression = ord(s[2])
+
+ # bytes, dimension, zsize
+ layout = ord(s[3]), i16(s[4:]), i16(s[10:])
+
+ # determine mode from bytes/zsize
+ if layout == (1, 2, 1):
+ self.mode = "L"
+ elif layout == (1, 3, 3):
+ self.mode = "RGB"
+ else:
+ raise SyntaxError, "unsupported SGI image mode"
+
+ # size
+ self.size = i16(s[6:]), i16(s[8:])
+
+ # decoder info
+ if compression == 0:
+ if self.mode == "RGB":
+ # RGB images are band interleaved
+ size = self.size[0]*self.size[1]
+ self.tile = [("raw", (0,0)+self.size, 512, ("R",0,1)),
+ ("raw", (0,0)+self.size, 512+size, ("G",0,1)),
+ ("raw", (0,0)+self.size, 512+2*size, ("B",0,1))]
+ else:
+ self.tile = [("raw", (0,0)+self.size, 512, (self.mode, 0, 1))]
+ if compression == 1:
+ self.tile = [("sgi_rle", (0,0)+self.size, 512, (self.mode, 0, 1))]
+
+#
+# registry
+
+Image.register_open("SGI", SgiImageFile, _accept)
+
+Image.register_extension("SGI", ".bw")
+Image.register_extension("SGI", ".rgb")
+Image.register_extension("SGI", ".rgba")
+
+Image.register_extension("SGI", ".sgi") # really?
diff --git a/Imaging/PIL/SpiderImagePlugin.py b/Imaging/PIL/SpiderImagePlugin.py
new file mode 100644
index 0000000..e0fd045
--- /dev/null
+++ b/Imaging/PIL/SpiderImagePlugin.py
@@ -0,0 +1,294 @@
+#
+# The Python Imaging Library.
+#
+# SPIDER image file handling
+#
+# History:
+# 2004-08-02 Created BB
+# 2006-03-02 added save method
+# 2006-03-13 added support for stack images
+#
+# Copyright (c) 2004 by Health Research Inc. (HRI) RENSSELAER, NY 12144.
+# Copyright (c) 2004 by William Baxter.
+# Copyright (c) 2004 by Secret Labs AB.
+# Copyright (c) 2004 by Fredrik Lundh.
+#
+
+##
+# Image plugin for the Spider image format. This format is is used
+# by the SPIDER software, in processing image data from electron
+# microscopy and tomography.
+##
+
+#
+# SpiderImagePlugin.py
+#
+# The Spider image format is used by SPIDER software, in processing
+# image data from electron microscopy and tomography.
+#
+# Spider home page:
+# http://www.wadsworth.org/spider_doc/spider/docs/spider.html
+#
+# Details about the Spider image format:
+# http://www.wadsworth.org/spider_doc/spider/docs/image_doc.html
+#
+
+import Image, ImageFile
+import os, string, struct, sys
+
+def isInt(f):
+ try:
+ i = int(f)
+ if f-i == 0: return 1
+ else: return 0
+ except:
+ return 0
+
+iforms = [1,3,-11,-12,-21,-22]
+
+# There is no magic number to identify Spider files, so just check a
+# series of header locations to see if they have reasonable values.
+# Returns no.of bytes in the header, if it is a valid Spider header,
+# otherwise returns 0
+
+def isSpiderHeader(t):
+ h = (99,) + t # add 1 value so can use spider header index start=1
+ # header values 1,2,5,12,13,22,23 should be integers
+ for i in [1,2,5,12,13,22,23]:
+ if not isInt(h[i]): return 0
+ # check iform
+ iform = int(h[5])
+ if not iform in iforms: return 0
+ # check other header values
+ labrec = int(h[13]) # no. records in file header
+ labbyt = int(h[22]) # total no. of bytes in header
+ lenbyt = int(h[23]) # record length in bytes
+ #print "labrec = %d, labbyt = %d, lenbyt = %d" % (labrec,labbyt,lenbyt)
+ if labbyt != (labrec * lenbyt): return 0
+ # looks like a valid header
+ return labbyt
+
+def isSpiderImage(filename):
+ fp = open(filename,'rb')
+ f = fp.read(92) # read 23 * 4 bytes
+ fp.close()
+ bigendian = 1
+ t = struct.unpack('>23f',f) # try big-endian first
+ hdrlen = isSpiderHeader(t)
+ if hdrlen == 0:
+ bigendian = 0
+ t = struct.unpack('<23f',f) # little-endian
+ hdrlen = isSpiderHeader(t)
+ return hdrlen
+
+
+class SpiderImageFile(ImageFile.ImageFile):
+
+ format = "SPIDER"
+ format_description = "Spider 2D image"
+
+ def _open(self):
+ # check header
+ n = 27 * 4 # read 27 float values
+ f = self.fp.read(n)
+
+ try:
+ self.bigendian = 1
+ t = struct.unpack('>27f',f) # try big-endian first
+ hdrlen = isSpiderHeader(t)
+ if hdrlen == 0:
+ self.bigendian = 0
+ t = struct.unpack('<27f',f) # little-endian
+ hdrlen = isSpiderHeader(t)
+ if hdrlen == 0:
+ raise SyntaxError, "not a valid Spider file"
+ except struct.error:
+ raise SyntaxError, "not a valid Spider file"
+
+ h = (99,) + t # add 1 value : spider header index starts at 1
+ iform = int(h[5])
+ if iform != 1:
+ raise SyntaxError, "not a Spider 2D image"
+
+ self.size = int(h[12]), int(h[2]) # size in pixels (width, height)
+ self.istack = int(h[24])
+ self.imgnumber = int(h[27])
+
+ if self.istack == 0 and self.imgnumber == 0:
+ # stk=0, img=0: a regular 2D image
+ offset = hdrlen
+ self.nimages = 1
+ elif self.istack > 0 and self.imgnumber == 0:
+ # stk>0, img=0: Opening the stack for the first time
+ self.imgbytes = int(h[12]) * int(h[2]) * 4
+ self.hdrlen = hdrlen
+ self.nimages = int(h[26])
+ # Point to the first image in the stack
+ offset = hdrlen * 2
+ self.imgnumber = 1
+ elif self.istack == 0 and self.imgnumber > 0:
+ # stk=0, img>0: an image within the stack
+ offset = hdrlen + self.stkoffset
+ self.istack = 2 # So Image knows it's still a stack
+ else:
+ raise SyntaxError, "inconsistent stack header values"
+
+ if self.bigendian:
+ self.rawmode = "F;32BF"
+ else:
+ self.rawmode = "F;32F"
+ self.mode = "F"
+
+ self.tile = [("raw", (0, 0) + self.size, offset,
+ (self.rawmode, 0, 1))]
+ self.__fp = self.fp # FIXME: hack
+
+ # 1st image index is zero (although SPIDER imgnumber starts at 1)
+ def tell(self):
+ if self.imgnumber < 1:
+ return 0
+ else:
+ return self.imgnumber - 1
+
+ def seek(self, frame):
+ if self.istack == 0:
+ return
+ if frame >= self.nimages:
+ raise EOFError, "attempt to seek past end of file"
+ self.stkoffset = self.hdrlen + frame * (self.hdrlen + self.imgbytes)
+ self.fp = self.__fp
+ self.fp.seek(self.stkoffset)
+ self._open()
+
+ # returns a byte image after rescaling to 0..255
+ def convert2byte(self, depth=255):
+ (min, max) = self.getextrema()
+ m = 1
+ if max != min:
+ m = depth / (max-min)
+ b = -m * min
+ return self.point(lambda i, m=m, b=b: i * m + b).convert("L")
+
+ # returns a ImageTk.PhotoImage object, after rescaling to 0..255
+ def tkPhotoImage(self):
+ import ImageTk
+ return ImageTk.PhotoImage(self.convert2byte(), palette=256)
+
+# --------------------------------------------------------------------
+# Image series
+
+# given a list of filenames, return a list of images
+def loadImageSeries(filelist=None):
+ " create a list of Image.images for use in montage "
+ if filelist == None or len(filelist) < 1:
+ return
+
+ imglist = []
+ for img in filelist:
+ if not os.path.exists(img):
+ print "unable to find %s" % img
+ continue
+ try:
+ im = Image.open(img).convert2byte()
+ except:
+ if not isSpiderImage(img):
+ print img + " is not a Spider image file"
+ continue
+ im.info['filename'] = img
+ imglist.append(im)
+ return imglist
+
+# --------------------------------------------------------------------
+# For saving images in Spider format
+
+def makeSpiderHeader(im):
+ nsam,nrow = im.size
+ lenbyt = nsam * 4 # There are labrec records in the header
+ labrec = 1024 / lenbyt
+ if 1024%lenbyt != 0: labrec += 1
+ labbyt = labrec * lenbyt
+ hdr = []
+ nvalues = labbyt / 4
+ for i in range(nvalues):
+ hdr.append(0.0)
+
+ if len(hdr) < 23:
+ return []
+
+ # NB these are Fortran indices
+ hdr[1] = 1.0 # nslice (=1 for an image)
+ hdr[2] = float(nrow) # number of rows per slice
+ hdr[5] = 1.0 # iform for 2D image
+ hdr[12] = float(nsam) # number of pixels per line
+ hdr[13] = float(labrec) # number of records in file header
+ hdr[22] = float(labbyt) # total number of bytes in header
+ hdr[23] = float(lenbyt) # record length in bytes
+
+ # adjust for Fortran indexing
+ hdr = hdr[1:]
+ hdr.append(0.0)
+ # pack binary data into a string
+ hdrstr = []
+ for v in hdr:
+ hdrstr.append(struct.pack('f',v))
+ return hdrstr
+
+def _save(im, fp, filename):
+ if im.mode[0] != "F":
+ im = im.convert('F')
+
+ hdr = makeSpiderHeader(im)
+ if len(hdr) < 256:
+ raise IOError, "Error creating Spider header"
+
+ # write the SPIDER header
+ try:
+ fp = open(filename, 'wb')
+ except:
+ raise IOError, "Unable to open %s for writing" % filename
+ fp.writelines(hdr)
+
+ rawmode = "F;32NF" #32-bit native floating point
+ ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode,0,1))])
+
+ fp.close()
+
+def _save_spider(im, fp, filename):
+ # get the filename extension and register it with Image
+ fn, ext = os.path.splitext(filename)
+ Image.register_extension("SPIDER", ext)
+ _save(im, fp, filename)
+
+# --------------------------------------------------------------------
+
+Image.register_open("SPIDER", SpiderImageFile)
+Image.register_save("SPIDER", _save_spider)
+
+if __name__ == "__main__":
+
+ if not sys.argv[1:]:
+ print "Syntax: python SpiderImagePlugin.py Spiderimage [outfile]"
+ sys.exit()
+
+ filename = sys.argv[1]
+ if not isSpiderImage(filename):
+ print "input image must be in Spider format"
+ sys.exit()
+
+ outfile = ""
+ if len(sys.argv[1:]) > 1:
+ outfile = sys.argv[2]
+
+ im = Image.open(filename)
+ print "image: " + str(im)
+ print "format: " + str(im.format)
+ print "size: " + str(im.size)
+ print "mode: " + str(im.mode)
+ print "max, min: ",
+ print im.getextrema()
+
+ if outfile != "":
+ # perform some image operation
+ im = im.transpose(Image.FLIP_LEFT_RIGHT)
+ print "saving a flipped version of %s as %s " % (os.path.basename(filename), outfile)
+ im.save(outfile, "SPIDER")
diff --git a/Imaging/PIL/SunImagePlugin.py b/Imaging/PIL/SunImagePlugin.py
new file mode 100644
index 0000000..2e7fe52
--- /dev/null
+++ b/Imaging/PIL/SunImagePlugin.py
@@ -0,0 +1,87 @@
+#
+# The Python Imaging Library.
+# $Id: SunImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# Sun image file handling
+#
+# History:
+# 1995-09-10 fl Created
+# 1996-05-28 fl Fixed 32-bit alignment
+# 1998-12-29 fl Import ImagePalette module
+# 2001-12-18 fl Fixed palette loading (from Jean-Claude Rimbault)
+#
+# Copyright (c) 1997-2001 by Secret Labs AB
+# Copyright (c) 1995-1996 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+
+__version__ = "0.3"
+
+
+import string
+import Image, ImageFile, ImagePalette
+
+
+def i16(c):
+ return ord(c[1]) + (ord(c[0])<<8)
+
+def i32(c):
+ return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
+
+
+def _accept(prefix):
+ return i32(prefix) == 0x59a66a95
+
+##
+# Image plugin for Sun raster files.
+
+class SunImageFile(ImageFile.ImageFile):
+
+ format = "SUN"
+ format_description = "Sun Raster File"
+
+ def _open(self):
+
+ # HEAD
+ s = self.fp.read(32)
+ if i32(s) != 0x59a66a95:
+ raise SyntaxError, "not an SUN raster file"
+
+ offset = 32
+
+ self.size = i32(s[4:8]), i32(s[8:12])
+
+ depth = i32(s[12:16])
+ if depth == 1:
+ self.mode, rawmode = "1", "1;I"
+ elif depth == 8:
+ self.mode = rawmode = "L"
+ elif depth == 24:
+ self.mode, rawmode = "RGB", "BGR"
+ else:
+ raise SyntaxError, "unsupported mode"
+
+ compression = i32(s[20:24])
+
+ if i32(s[24:28]) != 0:
+ length = i32(s[28:32])
+ offset = offset + length
+ self.palette = ImagePalette.raw("RGB;L", self.fp.read(length))
+ if self.mode == "L":
+ self.mode = rawmode = "P"
+
+ stride = (((self.size[0] * depth + 7) / 8) + 3) & (~3)
+
+ if compression == 1:
+ self.tile = [("raw", (0,0)+self.size, offset, (rawmode, stride))]
+ elif compression == 2:
+ self.tile = [("sun_rle", (0,0)+self.size, offset, rawmode)]
+
+#
+# registry
+
+Image.register_open("SUN", SunImageFile, _accept)
+
+Image.register_extension("SUN", ".ras")
diff --git a/Imaging/PIL/TarIO.py b/Imaging/PIL/TarIO.py
new file mode 100644
index 0000000..fbab8ca
--- /dev/null
+++ b/Imaging/PIL/TarIO.py
@@ -0,0 +1,57 @@
+#
+# The Python Imaging Library.
+# $Id: TarIO.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# read files from within a tar file
+#
+# History:
+# 95-06-18 fl Created
+# 96-05-28 fl Open files in binary mode
+#
+# Copyright (c) Secret Labs AB 1997.
+# Copyright (c) Fredrik Lundh 1995-96.
+#
+# See the README file for information on usage and redistribution.
+#
+
+import ContainerIO
+import string
+
+##
+# A file object that provides read access to a given member of a TAR
+# file.
+
+class TarIO(ContainerIO.ContainerIO):
+
+ ##
+ # Create file object.
+ #
+ # @param tarfile Name of TAR file.
+ # @param file Name of member file.
+
+ def __init__(self, tarfile, file):
+
+ fh = open(tarfile, "rb")
+
+ while 1:
+
+ s = fh.read(512)
+ if len(s) != 512:
+ raise IOError, "unexpected end of tar file"
+
+ name = s[:100]
+ i = string.find(name, chr(0))
+ if i == 0:
+ raise IOError, "cannot find subfile"
+ if i > 0:
+ name = name[:i]
+
+ size = string.atoi(s[124:136], 8)
+
+ if file == name:
+ break
+
+ fh.seek((size + 511) & (~511), 1)
+
+ # Open region
+ ContainerIO.ContainerIO.__init__(self, fh, fh.tell(), size)
diff --git a/Imaging/PIL/TgaImagePlugin.py b/Imaging/PIL/TgaImagePlugin.py
new file mode 100644
index 0000000..e709de8
--- /dev/null
+++ b/Imaging/PIL/TgaImagePlugin.py
@@ -0,0 +1,133 @@
+#
+# The Python Imaging Library.
+# $Id: TgaImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# TGA file handling
+#
+# History:
+# 95-09-01 fl created (reads 24-bit files only)
+# 97-01-04 fl support more TGA versions, including compressed images
+# 98-07-04 fl fixed orientation and alpha layer bugs
+# 98-09-11 fl fixed orientation for runlength decoder
+#
+# Copyright (c) Secret Labs AB 1997-98.
+# Copyright (c) Fredrik Lundh 1995-97.
+#
+# See the README file for information on usage and redistribution.
+#
+
+
+__version__ = "0.3"
+
+import Image, ImageFile, ImagePalette
+
+
+def i16(c):
+ return ord(c[0]) + (ord(c[1])<<8)
+
+def i32(c):
+ return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
+
+
+MODES = {
+ # map imagetype/depth to rawmode
+ (1, 8): "P",
+ (3, 1): "1",
+ (3, 8): "L",
+ (2, 16): "BGR;5",
+ (2, 24): "BGR",
+ (2, 32): "BGRA",
+}
+
+
+def _accept(prefix):
+ return prefix[0] == "\0"
+
+##
+# Image plugin for Targa files.
+
+class TgaImageFile(ImageFile.ImageFile):
+
+ format = "TGA"
+ format_description = "Targa"
+
+ def _open(self):
+
+ # process header
+ s = self.fp.read(18)
+
+ id = ord(s[0])
+
+ colormaptype = ord(s[1])
+ imagetype = ord(s[2])
+
+ depth = ord(s[16])
+
+ flags = ord(s[17])
+
+ self.size = i16(s[12:]), i16(s[14:])
+
+ # 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):
+ raise SyntaxError, "not a TGA file"
+
+ # image mode
+ if imagetype in (3, 11):
+ self.mode = "L"
+ if depth == 1:
+ self.mode = "1" # ???
+ elif imagetype in (1, 9):
+ self.mode = "P"
+ elif imagetype in (2, 10):
+ self.mode = "RGB"
+ if depth == 32:
+ self.mode = "RGBA"
+ else:
+ raise SyntaxError, "unknown TGA mode"
+
+ # orientation
+ orientation = flags & 0x30
+ if orientation == 0x20:
+ orientation = 1
+ elif not orientation:
+ orientation = -1
+ else:
+ raise SyntaxError, "unknown TGA orientation"
+
+ if imagetype & 8:
+ self.info["compression"] = "tga_rle"
+
+ if colormaptype:
+ # read palette
+ start, size, mapdepth = i16(s[3:]), i16(s[5:]), i16(s[7:])
+ if mapdepth == 16:
+ self.palette = ImagePalette.raw("BGR;16",
+ "\0"*2*start + self.fp.read(2*size))
+ elif mapdepth == 24:
+ self.palette = ImagePalette.raw("BGR",
+ "\0"*3*start + self.fp.read(3*size))
+ elif mapdepth == 32:
+ self.palette = ImagePalette.raw("BGRA",
+ "\0"*4*start + self.fp.read(4*size))
+
+ # setup tile descriptor
+ try:
+ rawmode = MODES[(imagetype&7, depth)]
+ if imagetype & 8:
+ # compressed
+ self.tile = [("tga_rle", (0, 0)+self.size,
+ self.fp.tell(), (rawmode, orientation, depth))]
+ else:
+ self.tile = [("raw", (0, 0)+self.size,
+ self.fp.tell(), (rawmode, 0, orientation))]
+ except KeyError:
+ pass # cannot decode
+
+#
+# registry
+
+Image.register_open("TGA", TgaImageFile, _accept)
+
+Image.register_extension("TGA", ".tga")
diff --git a/Imaging/PIL/TiffImagePlugin.py b/Imaging/PIL/TiffImagePlugin.py
new file mode 100644
index 0000000..178066c
--- /dev/null
+++ b/Imaging/PIL/TiffImagePlugin.py
@@ -0,0 +1,763 @@
+#
+# The Python Imaging Library.
+# $Id: TiffImagePlugin.py 2803 2006-07-31 19:18:57Z fredrik $
+#
+# TIFF file handling
+#
+# TIFF is a flexible, if somewhat aged, image file format originally
+# defined by Aldus. Although TIFF supports a wide variety of pixel
+# layouts and compression methods, the name doesn't really stand for
+# "thousands of incompatible file formats," it just feels that way.
+#
+# To read TIFF data from a stream, the stream must be seekable. For
+# progressive decoding, make sure to use TIFF files where the tag
+# directory is placed first in the file.
+#
+# History:
+# 1995-09-01 fl Created
+# 1996-05-04 fl Handle JPEGTABLES tag
+# 1996-05-18 fl Fixed COLORMAP support
+# 1997-01-05 fl Fixed PREDICTOR support
+# 1997-08-27 fl Added support for rational tags (from Perry Stoll)
+# 1998-01-10 fl Fixed seek/tell (from Jan Blom)
+# 1998-07-15 fl Use private names for internal variables
+# 1999-06-13 fl Rewritten for PIL 1.0 (1.0)
+# 2000-10-11 fl Additional fixes for Python 2.0 (1.1)
+# 2001-04-17 fl Fixed rewind support (seek to frame 0) (1.2)
+# 2001-05-12 fl Added write support for more tags (from Greg Couch) (1.3)
+# 2001-12-18 fl Added workaround for broken Matrox library
+# 2002-01-18 fl Don't mess up if photometric tag is missing (D. Alan Stewart)
+# 2003-05-19 fl Check FILLORDER tag
+# 2003-09-26 fl Added RGBa support
+# 2004-02-24 fl Added DPI support; fixed rational write support
+# 2005-02-07 fl Added workaround for broken Corel Draw 10 files
+# 2006-01-09 fl Added support for float/double tags (from Russell Nelson)
+#
+# Copyright (c) 1997-2006 by Secret Labs AB. All rights reserved.
+# Copyright (c) 1995-1997 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+__version__ = "1.3.5"
+
+import Image, ImageFile
+import ImagePalette
+
+import array, string, sys
+
+try:
+ if sys.byteorder == "little":
+ byteorder = "II"
+ else:
+ byteorder = "MM"
+except AttributeError:
+ if ord(array.array("i",[1]).tostring()[0]):
+ byteorder = "II"
+ else:
+ byteorder = "MM"
+
+#
+# --------------------------------------------------------------------
+# Read TIFF files
+
+def il16(c,o=0):
+ return ord(c[o]) + (ord(c[o+1])<<8)
+def il32(c,o=0):
+ return ord(c[o]) + (ord(c[o+1])<<8) + (ord(c[o+2])<<16) + (ord(c[o+3])<<24)
+def ol16(i):
+ return chr(i&255) + chr(i>>8&255)
+def ol32(i):
+ return chr(i&255) + chr(i>>8&255) + chr(i>>16&255) + chr(i>>24&255)
+
+def ib16(c,o=0):
+ return ord(c[o+1]) + (ord(c[o])<<8)
+def ib32(c,o=0):
+ return ord(c[o+3]) + (ord(c[o+2])<<8) + (ord(c[o+1])<<16) + (ord(c[o])<<24)
+
+# a few tag names, just to make the code below a bit more readable
+IMAGEWIDTH = 256
+IMAGELENGTH = 257
+BITSPERSAMPLE = 258
+COMPRESSION = 259
+PHOTOMETRIC_INTERPRETATION = 262
+FILLORDER = 266
+IMAGEDESCRIPTION = 270
+STRIPOFFSETS = 273
+SAMPLESPERPIXEL = 277
+ROWSPERSTRIP = 278
+STRIPBYTECOUNTS = 279
+X_RESOLUTION = 282
+Y_RESOLUTION = 283
+PLANAR_CONFIGURATION = 284
+RESOLUTION_UNIT = 296
+SOFTWARE = 305
+DATE_TIME = 306
+ARTIST = 315
+PREDICTOR = 317
+COLORMAP = 320
+EXTRASAMPLES = 338
+SAMPLEFORMAT = 339
+JPEGTABLES = 347
+COPYRIGHT = 33432
+IPTC_NAA_CHUNK = 33723 # newsphoto properties
+PHOTOSHOP_CHUNK = 34377 # photoshop properties
+
+COMPRESSION_INFO = {
+ # Compression => pil compression name
+ 1: "raw",
+ 2: "tiff_ccitt",
+ 3: "group3",
+ 4: "group4",
+ 5: "tiff_lzw",
+ 6: "tiff_jpeg", # obsolete
+ 7: "jpeg",
+ 32771: "tiff_raw_16", # 16-bit padding
+ 32773: "packbits"
+}
+
+OPEN_INFO = {
+ # (PhotoInterpretation, SampleFormat, FillOrder, BitsPerSample,
+ # ExtraSamples) => mode, rawmode
+ (0, 1, 1, (1,), ()): ("1", "1;I"),
+ (0, 1, 2, (1,), ()): ("1", "1;IR"),
+ (0, 1, 1, (8,), ()): ("L", "L;I"),
+ (0, 1, 2, (8,), ()): ("L", "L;IR"),
+ (1, 1, 1, (1,), ()): ("1", "1"),
+ (1, 1, 2, (1,), ()): ("1", "1;R"),
+ (1, 1, 1, (8,), ()): ("L", "L"),
+ (1, 1, 1, (8,8), (2,)): ("LA", "LA"),
+ (1, 1, 2, (8,), ()): ("L", "L;R"),
+ (1, 1, 1, (16,), ()): ("I;16", "I;16"),
+ (1, 2, 1, (16,), ()): ("I;16S", "I;16S"),
+ (1, 2, 1, (32,), ()): ("I", "I;32S"),
+ (1, 3, 1, (32,), ()): ("F", "F;32F"),
+ (2, 1, 1, (8,8,8), ()): ("RGB", "RGB"),
+ (2, 1, 2, (8,8,8), ()): ("RGB", "RGB;R"),
+ (2, 1, 1, (8,8,8,8), (0,)): ("RGBX", "RGBX"),
+ (2, 1, 1, (8,8,8,8), (1,)): ("RGBA", "RGBa"),
+ (2, 1, 1, (8,8,8,8), (2,)): ("RGBA", "RGBA"),
+ (2, 1, 1, (8,8,8,8), (999,)): ("RGBA", "RGBA"), # corel draw 10
+ (3, 1, 1, (1,), ()): ("P", "P;1"),
+ (3, 1, 2, (1,), ()): ("P", "P;1R"),
+ (3, 1, 1, (2,), ()): ("P", "P;2"),
+ (3, 1, 2, (2,), ()): ("P", "P;2R"),
+ (3, 1, 1, (4,), ()): ("P", "P;4"),
+ (3, 1, 2, (4,), ()): ("P", "P;4R"),
+ (3, 1, 1, (8,), ()): ("P", "P"),
+ (3, 1, 1, (8,8), (2,)): ("PA", "PA"),
+ (3, 1, 2, (8,), ()): ("P", "P;R"),
+ (5, 1, 1, (8,8,8,8), ()): ("CMYK", "CMYK"),
+ (6, 1, 1, (8,8,8), ()): ("YCbCr", "YCbCr"),
+ (8, 1, 1, (8,8,8), ()): ("LAB", "LAB"),
+}
+
+PREFIXES = ["MM\000\052", "II\052\000", "II\xBC\000"]
+
+def _accept(prefix):
+ return prefix[:4] in PREFIXES
+
+##
+# Wrapper for TIFF IFDs.
+
+class ImageFileDirectory:
+
+ # represents a TIFF tag directory. to speed things up,
+ # we don't decode tags unless they're asked for.
+
+ def __init__(self, prefix="II"):
+ self.prefix = prefix[:2]
+ if self.prefix == "MM":
+ self.i16, self.i32 = ib16, ib32
+ # FIXME: save doesn't yet support big-endian mode...
+ elif self.prefix == "II":
+ self.i16, self.i32 = il16, il32
+ self.o16, self.o32 = ol16, ol32
+ else:
+ raise SyntaxError("not a TIFF IFD")
+ self.reset()
+
+ def reset(self):
+ self.tags = {}
+ self.tagdata = {}
+ self.next = None
+
+ # dictionary API (sort of)
+
+ def keys(self):
+ return self.tagdata.keys() + self.tags.keys()
+
+ def items(self):
+ items = self.tags.items()
+ for tag in self.tagdata.keys():
+ items.append((tag, self[tag]))
+ return items
+
+ def __len__(self):
+ return len(self.tagdata) + len(self.tags)
+
+ def __getitem__(self, tag):
+ try:
+ return self.tags[tag]
+ except KeyError:
+ type, data = self.tagdata[tag] # unpack on the fly
+ size, handler = self.load_dispatch[type]
+ self.tags[tag] = data = handler(self, data)
+ del self.tagdata[tag]
+ return data
+
+ def get(self, tag, default=None):
+ try:
+ return self[tag]
+ except KeyError:
+ return default
+
+ def getscalar(self, tag, default=None):
+ try:
+ value = self[tag]
+ if len(value) != 1:
+ if tag == SAMPLEFORMAT:
+ # work around broken (?) matrox library
+ # (from Ted Wright, via Bob Klimek)
+ raise KeyError # use default
+ raise ValueError, "not a scalar"
+ return value[0]
+ except KeyError:
+ if default is None:
+ raise
+ return default
+
+ def has_key(self, tag):
+ return self.tags.has_key(tag) or self.tagdata.has_key(tag)
+
+ def __setitem__(self, tag, value):
+ if type(value) is not type(()):
+ value = (value,)
+ self.tags[tag] = value
+
+ # load primitives
+
+ load_dispatch = {}
+
+ def load_byte(self, data):
+ l = []
+ for i in range(len(data)):
+ l.append(ord(data[i]))
+ return tuple(l)
+ load_dispatch[1] = (1, load_byte)
+
+ def load_string(self, data):
+ if data[-1:] == '\0':
+ data = data[:-1]
+ return data
+ load_dispatch[2] = (1, load_string)
+
+ def load_short(self, data):
+ l = []
+ for i in range(0, len(data), 2):
+ l.append(self.i16(data, i))
+ return tuple(l)
+ load_dispatch[3] = (2, load_short)
+
+ def load_long(self, data):
+ l = []
+ for i in range(0, len(data), 4):
+ l.append(self.i32(data, i))
+ return tuple(l)
+ load_dispatch[4] = (4, load_long)
+
+ def load_rational(self, data):
+ l = []
+ for i in range(0, len(data), 8):
+ l.append((self.i32(data, i), self.i32(data, i+4)))
+ return tuple(l)
+ load_dispatch[5] = (8, load_rational)
+
+ def load_float(self, data):
+ a = array.array("f", data)
+ if self.prefix != byteorder:
+ a.byteswap()
+ return tuple(a)
+ load_dispatch[11] = (4, load_float)
+
+ def load_double(self, data):
+ a = array.array("d", data)
+ if self.prefix != byteorder:
+ a.byteswap()
+ return tuple(a)
+ load_dispatch[12] = (8, load_double)
+
+ def load_undefined(self, data):
+ # Untyped data
+ return data
+ load_dispatch[7] = (1, load_undefined)
+
+ def load(self, fp):
+ # load tag dictionary
+
+ self.reset()
+
+ i16 = self.i16
+ i32 = self.i32
+
+ for i in range(i16(fp.read(2))):
+
+ ifd = fp.read(12)
+
+ tag, typ = i16(ifd), i16(ifd, 2)
+
+ if Image.DEBUG:
+ import TiffTags
+ tagname = TiffTags.TAGS.get(tag, "unknown")
+ typname = TiffTags.TYPES.get(typ, "unknown")
+ print "tag: %s (%d)" % (tagname, tag),
+ print "- type: %s (%d)" % (typname, typ),
+
+ try:
+ dispatch = self.load_dispatch[typ]
+ except KeyError:
+ if Image.DEBUG:
+ print "- unsupported type", typ
+ continue # ignore unsupported type
+
+ size, handler = dispatch
+
+ size = size * i32(ifd, 4)
+
+ # Get and expand tag value
+ if size > 4:
+ here = fp.tell()
+ fp.seek(i32(ifd, 8))
+ data = ImageFile._safe_read(fp, size)
+ fp.seek(here)
+ else:
+ data = ifd[8:8+size]
+
+ if len(data) != size:
+ raise IOError, "not enough data"
+
+ self.tagdata[tag] = typ, data
+
+ if Image.DEBUG:
+ if tag in (COLORMAP, IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK):
+ print "- value: <table: %d bytes>" % size
+ else:
+ print "- value:", self[tag]
+
+ self.next = i32(fp.read(4))
+
+ # save primitives
+
+ def save(self, fp):
+
+ o16 = self.o16
+ o32 = self.o32
+
+ fp.write(o16(len(self.tags)))
+
+ # always write in ascending tag order
+ tags = self.tags.items()
+ tags.sort()
+
+ directory = []
+ append = directory.append
+
+ offset = fp.tell() + len(self.tags) * 12 + 4
+
+ stripoffsets = None
+
+ # pass 1: convert tags to binary format
+ for tag, value in tags:
+
+ if Image.DEBUG:
+ import TiffTags
+ tagname = TiffTags.TAGS.get(tag, "unknown")
+ print "save: %s (%d)" % (tagname, tag),
+ print "- value:", value
+
+ if type(value[0]) is type(""):
+ # string data
+ typ = 2
+ data = value = string.join(value, "\0") + "\0"
+
+ else:
+ # integer data
+ if tag == STRIPOFFSETS:
+ stripoffsets = len(directory)
+ typ = 4 # to avoid catch-22
+ elif tag in (X_RESOLUTION, Y_RESOLUTION):
+ # identify rational data fields
+ typ = 5
+ else:
+ typ = 3
+ for v in value:
+ if v >= 65536:
+ typ = 4
+ if typ == 3:
+ data = string.join(map(o16, value), "")
+ else:
+ data = string.join(map(o32, value), "")
+
+ # figure out if data fits into the directory
+ if len(data) == 4:
+ append((tag, typ, len(value), data, ""))
+ elif len(data) < 4:
+ append((tag, typ, len(value), data + (4-len(data))*"\0", ""))
+ else:
+ count = len(value)
+ if typ == 5:
+ count = count / 2 # adjust for rational data field
+ append((tag, typ, count, o32(offset), data))
+ offset = offset + len(data)
+ if offset & 1:
+ offset = offset + 1 # word padding
+
+ # update strip offset data to point beyond auxiliary data
+ if stripoffsets is not None:
+ tag, typ, count, value, data = directory[stripoffsets]
+ assert not data, "multistrip support not yet implemented"
+ value = o32(self.i32(value) + offset)
+ directory[stripoffsets] = tag, typ, count, value, data
+
+ # pass 2: write directory to file
+ for tag, typ, count, value, data in directory:
+ if Image.DEBUG > 1:
+ print tag, typ, count, repr(value), repr(data)
+ fp.write(o16(tag) + o16(typ) + o32(count) + value)
+ fp.write("\0\0\0\0") # end of directory
+
+ # pass 3: write auxiliary data to file
+ for tag, typ, count, value, data in directory:
+ fp.write(data)
+ if len(data) & 1:
+ fp.write("\0")
+
+ return offset
+
+##
+# Image plugin for TIFF files.
+
+class TiffImageFile(ImageFile.ImageFile):
+
+ format = "TIFF"
+ format_description = "Adobe TIFF"
+
+ def _open(self):
+ "Open the first image in a TIFF file"
+
+ # Header
+ ifh = self.fp.read(8)
+
+ if ifh[:4] not in PREFIXES:
+ raise SyntaxError, "not a TIFF file"
+
+ # image file directory (tag dictionary)
+ self.tag = self.ifd = ImageFileDirectory(ifh[:2])
+
+ # setup frame pointers
+ self.__first = self.__next = self.ifd.i32(ifh, 4)
+ self.__frame = -1
+ self.__fp = self.fp
+
+ # and load the first frame
+ self._seek(0)
+
+ def seek(self, frame):
+ "Select a given frame as current image"
+
+ if frame < 0:
+ frame = 0
+ self._seek(frame)
+
+ def tell(self):
+ "Return the current frame number"
+
+ return self._tell()
+
+ def _seek(self, frame):
+
+ self.fp = self.__fp
+ if frame < self.__frame:
+ # rewind file
+ self.__frame = -1
+ self.__next = self.__first
+ while self.__frame < frame:
+ if not self.__next:
+ raise EOFError, "no more images in TIFF file"
+ self.fp.seek(self.__next)
+ self.tag.load(self.fp)
+ self.__next = self.tag.next
+ self.__frame = self.__frame + 1
+ self._setup()
+
+ def _tell(self):
+
+ return self.__frame
+
+ def _decoder(self, rawmode, layer):
+ "Setup decoder contexts"
+
+ args = None
+ if rawmode == "RGB" and self._planar_configuration == 2:
+ rawmode = rawmode[layer]
+ compression = self._compression
+ if compression == "raw":
+ args = (rawmode, 0, 1)
+ elif compression == "jpeg":
+ args = rawmode, ""
+ if self.tag.has_key(JPEGTABLES):
+ # Hack to handle abbreviated JPEG headers
+ self.tile_prefix = self.tag[JPEGTABLES]
+ elif compression == "packbits":
+ args = rawmode
+ elif compression == "tiff_lzw":
+ args = rawmode
+ if self.tag.has_key(317):
+ # Section 14: Differencing Predictor
+ self.decoderconfig = (self.tag[PREDICTOR][0],)
+
+ return args
+
+ def _setup(self):
+ "Setup this image object based on current tags"
+
+ if self.tag.has_key(0xBC01):
+ raise IOError, "Windows Media Photo files not yet supported"
+
+ getscalar = self.tag.getscalar
+
+ # extract relevant tags
+ self._compression = COMPRESSION_INFO[getscalar(COMPRESSION, 1)]
+ self._planar_configuration = getscalar(PLANAR_CONFIGURATION, 1)
+
+ # photometric is a required tag, but not everyone is reading
+ # the specification
+ photo = getscalar(PHOTOMETRIC_INTERPRETATION, 0)
+
+ fillorder = getscalar(FILLORDER, 1)
+
+ if Image.DEBUG:
+ print "*** Summary ***"
+ print "- compression:", self._compression
+ print "- photometric_interpretation:", photo
+ print "- planar_configuration:", self._planar_configuration
+ print "- fill_order:", fillorder
+
+ # size
+ xsize = getscalar(IMAGEWIDTH)
+ ysize = getscalar(IMAGELENGTH)
+ self.size = xsize, ysize
+
+ if Image.DEBUG:
+ print "- size:", self.size
+
+ format = getscalar(SAMPLEFORMAT, 1)
+
+ # mode: check photometric interpretation and bits per pixel
+ key = (
+ photo, format, fillorder,
+ self.tag.get(BITSPERSAMPLE, (1,)),
+ self.tag.get(EXTRASAMPLES, ())
+ )
+ if Image.DEBUG:
+ print "format key:", key
+ try:
+ self.mode, rawmode = OPEN_INFO[key]
+ except KeyError:
+ if Image.DEBUG:
+ print "- unsupported format"
+ raise SyntaxError, "unknown pixel mode"
+
+ if Image.DEBUG:
+ print "- raw mode:", rawmode
+ print "- pil mode:", self.mode
+
+ self.info["compression"] = self._compression
+
+ xdpi = getscalar(X_RESOLUTION, (1, 1))
+ ydpi = getscalar(Y_RESOLUTION, (1, 1))
+
+ if xdpi and ydpi and getscalar(RESOLUTION_UNIT, 1) == 1:
+ xdpi = xdpi[0] / (xdpi[1] or 1)
+ ydpi = ydpi[0] / (ydpi[1] or 1)
+ self.info["dpi"] = xdpi, ydpi
+
+ # build tile descriptors
+ x = y = l = 0
+ self.tile = []
+ if self.tag.has_key(STRIPOFFSETS):
+ # striped image
+ h = getscalar(ROWSPERSTRIP, ysize)
+ w = self.size[0]
+ a = None
+ for o in self.tag[STRIPOFFSETS]:
+ if not a:
+ a = self._decoder(rawmode, l)
+ self.tile.append(
+ (self._compression,
+ (0, min(y, ysize), w, min(y+h, ysize)),
+ o, a))
+ y = y + h
+ if y >= self.size[1]:
+ x = y = 0
+ l = l + 1
+ a = None
+ elif self.tag.has_key(324):
+ # tiled image
+ w = getscalar(322)
+ h = getscalar(323)
+ a = None
+ for o in self.tag[324]:
+ if not a:
+ a = self._decoder(rawmode, l)
+ # FIXME: this doesn't work if the image size
+ # is not a multiple of the tile size...
+ self.tile.append(
+ (self._compression,
+ (x, y, x+w, y+h),
+ o, a))
+ x = x + w
+ if x >= self.size[0]:
+ x, y = 0, y + h
+ if y >= self.size[1]:
+ x = y = 0
+ l = l + 1
+ a = None
+ else:
+ if Image.DEBUG:
+ print "- unsupported data organization"
+ raise SyntaxError("unknown data organization")
+
+ # fixup palette descriptor
+ if self.mode == "P":
+ palette = map(lambda a: chr(a / 256), self.tag[COLORMAP])
+ self.palette = ImagePalette.raw("RGB;L", string.join(palette, ""))
+
+#
+# --------------------------------------------------------------------
+# Write TIFF files
+
+# little endian is default
+
+SAVE_INFO = {
+ # mode => rawmode, photometrics, sampleformat, bitspersample, extra
+ "1": ("1", 1, 1, (1,), None),
+ "L": ("L", 1, 1, (8,), None),
+ "LA": ("LA", 1, 1, (8,8), 2),
+ "P": ("P", 3, 1, (8,), None),
+ "PA": ("PA", 3, 1, (8,8), 2),
+ "I": ("I;32S", 1, 2, (32,), None),
+ "I;16": ("I;16", 1, 1, (16,), None),
+ "I;16S": ("I;16S", 1, 2, (16,), None),
+ "F": ("F;32F", 1, 3, (32,), None),
+ "RGB": ("RGB", 2, 1, (8,8,8), None),
+ "RGBX": ("RGBX", 2, 1, (8,8,8,8), 0),
+ "RGBA": ("RGBA", 2, 1, (8,8,8,8), 2),
+ "CMYK": ("CMYK", 5, 1, (8,8,8,8), None),
+ "YCbCr": ("YCbCr", 6, 1, (8,8,8), None),
+ "LAB": ("LAB", 8, 1, (8,8,8), None),
+}
+
+def _cvt_res(value):
+ # convert value to TIFF rational number -- (numerator, denominator)
+ if type(value) in (type([]), type(())):
+ assert(len(value) % 2 == 0)
+ return value
+ if type(value) == type(1):
+ return (value, 1)
+ value = float(value)
+ return (int(value * 65536), 65536)
+
+def _save(im, fp, filename):
+
+ try:
+ rawmode, photo, format, bits, extra = SAVE_INFO[im.mode]
+ except KeyError:
+ raise IOError, "cannot write mode %s as TIFF" % im.mode
+
+ ifd = ImageFileDirectory()
+
+ # tiff header (write via IFD to get everything right)
+ fp.write(ifd.prefix + ifd.o16(42) + ifd.o32(8))
+
+ ifd[IMAGEWIDTH] = im.size[0]
+ ifd[IMAGELENGTH] = im.size[1]
+
+ # additions written by Greg Couch, gregc@cgl.ucsf.edu
+ # inspired by image-sig posting from Kevin Cazabon, kcazabon@home.com
+ if hasattr(im, 'tag'):
+ # preserve tags from original TIFF image file
+ for key in (RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION):
+ if im.tag.tagdata.has_key(key):
+ ifd[key] = im.tag.tagdata.get(key)
+ if im.encoderinfo.has_key("description"):
+ ifd[IMAGEDESCRIPTION] = im.encoderinfo["description"]
+ if im.encoderinfo.has_key("resolution"):
+ ifd[X_RESOLUTION] = ifd[Y_RESOLUTION] \
+ = _cvt_res(im.encoderinfo["resolution"])
+ if im.encoderinfo.has_key("x resolution"):
+ ifd[X_RESOLUTION] = _cvt_res(im.encoderinfo["x resolution"])
+ if im.encoderinfo.has_key("y resolution"):
+ ifd[Y_RESOLUTION] = _cvt_res(im.encoderinfo["y resolution"])
+ if im.encoderinfo.has_key("resolution unit"):
+ unit = im.encoderinfo["resolution unit"]
+ if unit == "inch":
+ ifd[RESOLUTION_UNIT] = 2
+ elif unit == "cm" or unit == "centimeter":
+ ifd[RESOLUTION_UNIT] = 3
+ else:
+ ifd[RESOLUTION_UNIT] = 1
+ if im.encoderinfo.has_key("software"):
+ ifd[SOFTWARE] = im.encoderinfo["software"]
+ if im.encoderinfo.has_key("date time"):
+ ifd[DATE_TIME] = im.encoderinfo["date time"]
+ if im.encoderinfo.has_key("artist"):
+ ifd[ARTIST] = im.encoderinfo["artist"]
+ if im.encoderinfo.has_key("copyright"):
+ ifd[COPYRIGHT] = im.encoderinfo["copyright"]
+
+ dpi = im.encoderinfo.get("dpi")
+ if dpi:
+ ifd[RESOLUTION_UNIT] = 1
+ ifd[X_RESOLUTION] = _cvt_res(dpi[0])
+ ifd[Y_RESOLUTION] = _cvt_res(dpi[1])
+
+ if bits != (1,):
+ ifd[BITSPERSAMPLE] = bits
+ if len(bits) != 1:
+ ifd[SAMPLESPERPIXEL] = len(bits)
+ if extra is not None:
+ ifd[EXTRASAMPLES] = extra
+ if format != 1:
+ ifd[SAMPLEFORMAT] = format
+
+ ifd[PHOTOMETRIC_INTERPRETATION] = photo
+
+ if im.mode == "P":
+ lut = im.im.getpalette("RGB", "RGB;L")
+ ifd[COLORMAP] = tuple(map(lambda v: ord(v) * 256, lut))
+
+ # data orientation
+ stride = len(bits) * ((im.size[0]*bits[0]+7)/8)
+ ifd[ROWSPERSTRIP] = im.size[1]
+ ifd[STRIPBYTECOUNTS] = stride * im.size[1]
+ ifd[STRIPOFFSETS] = 0 # this is adjusted by IFD writer
+ ifd[COMPRESSION] = 1 # no compression
+
+ offset = ifd.save(fp)
+
+ ImageFile._save(im, fp, [
+ ("raw", (0,0)+im.size, offset, (rawmode, stride, 1))
+ ])
+
+#
+# --------------------------------------------------------------------
+# Register
+
+Image.register_open("TIFF", TiffImageFile, _accept)
+Image.register_save("TIFF", _save)
+
+Image.register_extension("TIFF", ".tif")
+Image.register_extension("TIFF", ".tiff")
+
+Image.register_mime("TIFF", "image/tiff")
diff --git a/Imaging/PIL/TiffTags.py b/Imaging/PIL/TiffTags.py
new file mode 100644
index 0000000..2795fc3
--- /dev/null
+++ b/Imaging/PIL/TiffTags.py
@@ -0,0 +1,200 @@
+#
+# The Python Imaging Library.
+# $Id: TiffTags.py 2340 2005-03-25 08:05:37Z fredrik $
+#
+# TIFF tags
+#
+# This module provides clear-text names for various well-known
+# TIFF tags. the TIFF codec works just fine without it.
+#
+# Copyright (c) Secret Labs AB 1999.
+#
+# See the README file for information on usage and redistribution.
+#
+
+##
+# This module provides constants and clear-text names for various
+# well-known TIFF tags.
+##
+
+##
+# Map tag numbers (or tag number, tag value tuples) to tag names.
+
+TAGS = {
+
+ 254: "NewSubfileType",
+ 255: "SubfileType",
+ 256: "ImageWidth",
+ 257: "ImageLength",
+ 258: "BitsPerSample",
+
+ 259: "Compression",
+ (259, 1): "Uncompressed",
+ (259, 2): "CCITT 1d",
+ (259, 3): "Group 3 Fax",
+ (259, 4): "Group 4 Fax",
+ (259, 5): "LZW",
+ (259, 6): "JPEG",
+ (259, 32773): "PackBits",
+
+ 262: "PhotometricInterpretation",
+ (262, 0): "WhiteIsZero",
+ (262, 1): "BlackIsZero",
+ (262, 2): "RGB",
+ (262, 3): "RGB Palette",
+ (262, 4): "Transparency Mask",
+ (262, 5): "CMYK",
+ (262, 6): "YCbCr",
+ (262, 8): "CieLAB",
+ (262, 32803): "CFA", # TIFF/EP, Adobe DNG
+ (262, 32892): "LinearRaw", # Adobe DNG
+
+ 263: "Thresholding",
+ 264: "CellWidth",
+ 265: "CellHeight",
+ 266: "FillOrder",
+ 269: "DocumentName",
+
+ 270: "ImageDescription",
+ 271: "Make",
+ 272: "Model",
+ 273: "StripOffsets",
+ 274: "Orientation",
+ 277: "SamplesPerPixel",
+ 278: "RowsPerStrip",
+ 279: "StripByteCounts",
+
+ 280: "MinSampleValue",
+ 281: "MaxSampleValue",
+ 282: "XResolution",
+ 283: "YResolution",
+ 284: "PlanarConfiguration",
+ (284, 1): "Contigous",
+ (284, 2): "Separate",
+
+ 285: "PageName",
+ 286: "XPosition",
+ 287: "YPosition",
+ 288: "FreeOffsets",
+ 289: "FreeByteCounts",
+
+ 290: "GrayResponseUnit",
+ 291: "GrayResponseCurve",
+ 292: "T4Options",
+ 293: "T6Options",
+ 296: "ResolutionUnit",
+ 297: "PageNumber",
+
+ 301: "TransferFunction",
+ 305: "Software",
+ 306: "DateTime",
+
+ 315: "Artist",
+ 316: "HostComputer",
+ 317: "Predictor",
+ 318: "WhitePoint",
+ 319: "PrimaryChromaticies",
+
+ 320: "ColorMap",
+ 321: "HalftoneHints",
+ 322: "TileWidth",
+ 323: "TileLength",
+ 324: "TileOffsets",
+ 325: "TileByteCounts",
+
+ 332: "InkSet",
+ 333: "InkNames",
+ 334: "NumberOfInks",
+ 336: "DotRange",
+ 337: "TargetPrinter",
+ 338: "ExtraSamples",
+ 339: "SampleFormat",
+
+ 340: "SMinSampleValue",
+ 341: "SMaxSampleValue",
+ 342: "TransferRange",
+
+ 347: "JPEGTables",
+
+ # obsolete JPEG tags
+ 512: "JPEGProc",
+ 513: "JPEGInterchangeFormat",
+ 514: "JPEGInterchangeFormatLength",
+ 515: "JPEGRestartInterval",
+ 517: "JPEGLosslessPredictors",
+ 518: "JPEGPointTransforms",
+ 519: "JPEGQTables",
+ 520: "JPEGDCTables",
+ 521: "JPEGACTables",
+
+ 529: "YCbCrCoefficients",
+ 530: "YCbCrSubSampling",
+ 531: "YCbCrPositioning",
+ 532: "ReferenceBlackWhite",
+
+ 33432: "Copyright",
+
+ # various extensions (should check specs for "official" names)
+ 33723: "IptcNaaInfo",
+ 34377: "PhotoshopInfo",
+
+ # Adobe DNG
+ 50706: "DNGVersion",
+ 50707: "DNGBackwardVersion",
+ 50708: "UniqueCameraModel",
+ 50709: "LocalizedCameraModel",
+ 50710: "CFAPlaneColor",
+ 50711: "CFALayout",
+ 50712: "LinearizationTable",
+ 50713: "BlackLevelRepeatDim",
+ 50714: "BlackLevel",
+ 50715: "BlackLevelDeltaH",
+ 50716: "BlackLevelDeltaV",
+ 50717: "WhiteLevel",
+ 50718: "DefaultScale",
+ 50741: "BestQualityScale",
+ 50719: "DefaultCropOrigin",
+ 50720: "DefaultCropSize",
+ 50778: "CalibrationIlluminant1",
+ 50779: "CalibrationIlluminant2",
+ 50721: "ColorMatrix1",
+ 50722: "ColorMatrix2",
+ 50723: "CameraCalibration1",
+ 50724: "CameraCalibration2",
+ 50725: "ReductionMatrix1",
+ 50726: "ReductionMatrix2",
+ 50727: "AnalogBalance",
+ 50728: "AsShotNeutral",
+ 50729: "AsShotWhiteXY",
+ 50730: "BaselineExposure",
+ 50731: "BaselineNoise",
+ 50732: "BaselineSharpness",
+ 50733: "BayerGreenSplit",
+ 50734: "LinearResponseLimit",
+ 50735: "CameraSerialNumber",
+ 50736: "LensInfo",
+ 50737: "ChromaBlurRadius",
+ 50738: "AntiAliasStrength",
+ 50740: "DNGPrivateData",
+ 50741: "MakerNoteSafety",
+}
+
+##
+# Map type numbers to type names.
+
+TYPES = {
+
+ 1: "byte",
+ 2: "ascii",
+ 3: "short",
+ 4: "long",
+ 5: "rational",
+ 6: "signed byte",
+ 7: "undefined",
+ 8: "signed short",
+ 9: "signed long",
+ 10: "signed rational",
+ 11: "float",
+ 12: "double",
+
+}
diff --git a/Imaging/PIL/WalImageFile.py b/Imaging/PIL/WalImageFile.py
new file mode 100644
index 0000000..34e7fc2
--- /dev/null
+++ b/Imaging/PIL/WalImageFile.py
@@ -0,0 +1,125 @@
+#
+# The Python Imaging Library.
+# $Id: WalImageFile.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# WAL file handling
+#
+# History:
+# 2003-04-23 fl created
+#
+# Copyright (c) 2003 by Fredrik Lundh.
+#
+# See the README file for information on usage and redistribution.
+#
+
+# NOTE: This format cannot be automatically recognized, so the reader
+# is not registered for use with Image.open(). To open a WEL file, use
+# the WalImageFile.open() function instead.
+
+# This reader is based on the specification available from:
+# http://www.flipcode.com/tutorials/tut_q2levels.shtml
+# and has been tested with a few sample files found using google.
+
+import Image
+
+def i32(c, o=0):
+ return ord(c[o])+(ord(c[o+1])<<8)+(ord(c[o+2])<<16)+(ord(c[o+3])<<24)
+
+##
+# Load texture from a Quake2 WAL texture file.
+# <p>
+# By default, a Quake2 standard palette is attached to the texture.
+# To override the palette, use the <b>putpalette</b> method.
+#
+# @param filename WAL file name, or an opened file handle.
+# @return An image instance.
+
+def open(filename):
+ # FIXME: modify to return a WalImageFile instance instead of
+ # plain Image object ?
+
+ if hasattr(filename, "read"):
+ fp = filename
+ else:
+ import __builtin__
+ fp = __builtin__.open(filename, "rb")
+
+ # read header fields
+ header = fp.read(32+24+32+12)
+ size = i32(header, 32), i32(header, 36)
+ offset = i32(header, 40)
+
+ # load pixel data
+ fp.seek(offset)
+
+ im = Image.fromstring("P", size, fp.read(size[0] * size[1]))
+ im.putpalette(quake2palette)
+
+ im.format = "WAL"
+ im.format_description = "Quake2 Texture"
+
+ # strings are null-terminated
+ im.info["name"] = header[:32].split("\0", 1)[0]
+ next_name = header[56:56+32].split("\0", 1)[0]
+ if next_name:
+ im.info["next_name"] = next_name
+
+ return im
+
+
+quake2palette = (
+ # default palette taken from piffo 0.93 by Hans Häggström
+ "\x01\x01\x01\x0b\x0b\x0b\x12\x12\x12\x17\x17\x17\x1b\x1b\x1b\x1e"
+ "\x1e\x1e\x22\x22\x22\x26\x26\x26\x29\x29\x29\x2c\x2c\x2c\x2f\x2f"
+ "\x2f\x32\x32\x32\x35\x35\x35\x37\x37\x37\x3a\x3a\x3a\x3c\x3c\x3c"
+ "\x24\x1e\x13\x22\x1c\x12\x20\x1b\x12\x1f\x1a\x10\x1d\x19\x10\x1b"
+ "\x17\x0f\x1a\x16\x0f\x18\x14\x0d\x17\x13\x0d\x16\x12\x0d\x14\x10"
+ "\x0b\x13\x0f\x0b\x10\x0d\x0a\x0f\x0b\x0a\x0d\x0b\x07\x0b\x0a\x07"
+ "\x23\x23\x26\x22\x22\x25\x22\x20\x23\x21\x1f\x22\x20\x1e\x20\x1f"
+ "\x1d\x1e\x1d\x1b\x1c\x1b\x1a\x1a\x1a\x19\x19\x18\x17\x17\x17\x16"
+ "\x16\x14\x14\x14\x13\x13\x13\x10\x10\x10\x0f\x0f\x0f\x0d\x0d\x0d"
+ "\x2d\x28\x20\x29\x24\x1c\x27\x22\x1a\x25\x1f\x17\x38\x2e\x1e\x31"
+ "\x29\x1a\x2c\x25\x17\x26\x20\x14\x3c\x30\x14\x37\x2c\x13\x33\x28"
+ "\x12\x2d\x24\x10\x28\x1f\x0f\x22\x1a\x0b\x1b\x14\x0a\x13\x0f\x07"
+ "\x31\x1a\x16\x30\x17\x13\x2e\x16\x10\x2c\x14\x0d\x2a\x12\x0b\x27"
+ "\x0f\x0a\x25\x0f\x07\x21\x0d\x01\x1e\x0b\x01\x1c\x0b\x01\x1a\x0b"
+ "\x01\x18\x0a\x01\x16\x0a\x01\x13\x0a\x01\x10\x07\x01\x0d\x07\x01"
+ "\x29\x23\x1e\x27\x21\x1c\x26\x20\x1b\x25\x1f\x1a\x23\x1d\x19\x21"
+ "\x1c\x18\x20\x1b\x17\x1e\x19\x16\x1c\x18\x14\x1b\x17\x13\x19\x14"
+ "\x10\x17\x13\x0f\x14\x10\x0d\x12\x0f\x0b\x0f\x0b\x0a\x0b\x0a\x07"
+ "\x26\x1a\x0f\x23\x19\x0f\x20\x17\x0f\x1c\x16\x0f\x19\x13\x0d\x14"
+ "\x10\x0b\x10\x0d\x0a\x0b\x0a\x07\x33\x22\x1f\x35\x29\x26\x37\x2f"
+ "\x2d\x39\x35\x34\x37\x39\x3a\x33\x37\x39\x30\x34\x36\x2b\x31\x34"
+ "\x27\x2e\x31\x22\x2b\x2f\x1d\x28\x2c\x17\x25\x2a\x0f\x20\x26\x0d"
+ "\x1e\x25\x0b\x1c\x22\x0a\x1b\x20\x07\x19\x1e\x07\x17\x1b\x07\x14"
+ "\x18\x01\x12\x16\x01\x0f\x12\x01\x0b\x0d\x01\x07\x0a\x01\x01\x01"
+ "\x2c\x21\x21\x2a\x1f\x1f\x29\x1d\x1d\x27\x1c\x1c\x26\x1a\x1a\x24"
+ "\x18\x18\x22\x17\x17\x21\x16\x16\x1e\x13\x13\x1b\x12\x12\x18\x10"
+ "\x10\x16\x0d\x0d\x12\x0b\x0b\x0d\x0a\x0a\x0a\x07\x07\x01\x01\x01"
+ "\x2e\x30\x29\x2d\x2e\x27\x2b\x2c\x26\x2a\x2a\x24\x28\x29\x23\x27"
+ "\x27\x21\x26\x26\x1f\x24\x24\x1d\x22\x22\x1c\x1f\x1f\x1a\x1c\x1c"
+ "\x18\x19\x19\x16\x17\x17\x13\x13\x13\x10\x0f\x0f\x0d\x0b\x0b\x0a"
+ "\x30\x1e\x1b\x2d\x1c\x19\x2c\x1a\x17\x2a\x19\x14\x28\x17\x13\x26"
+ "\x16\x10\x24\x13\x0f\x21\x12\x0d\x1f\x10\x0b\x1c\x0f\x0a\x19\x0d"
+ "\x0a\x16\x0b\x07\x12\x0a\x07\x0f\x07\x01\x0a\x01\x01\x01\x01\x01"
+ "\x28\x29\x38\x26\x27\x36\x25\x26\x34\x24\x24\x31\x22\x22\x2f\x20"
+ "\x21\x2d\x1e\x1f\x2a\x1d\x1d\x27\x1b\x1b\x25\x19\x19\x21\x17\x17"
+ "\x1e\x14\x14\x1b\x13\x12\x17\x10\x0f\x13\x0d\x0b\x0f\x0a\x07\x07"
+ "\x2f\x32\x29\x2d\x30\x26\x2b\x2e\x24\x29\x2c\x21\x27\x2a\x1e\x25"
+ "\x28\x1c\x23\x26\x1a\x21\x25\x18\x1e\x22\x14\x1b\x1f\x10\x19\x1c"
+ "\x0d\x17\x1a\x0a\x13\x17\x07\x10\x13\x01\x0d\x0f\x01\x0a\x0b\x01"
+ "\x01\x3f\x01\x13\x3c\x0b\x1b\x39\x10\x20\x35\x14\x23\x31\x17\x23"
+ "\x2d\x18\x23\x29\x18\x3f\x3f\x3f\x3f\x3f\x39\x3f\x3f\x31\x3f\x3f"
+ "\x2a\x3f\x3f\x20\x3f\x3f\x14\x3f\x3c\x12\x3f\x39\x0f\x3f\x35\x0b"
+ "\x3f\x32\x07\x3f\x2d\x01\x3d\x2a\x01\x3b\x26\x01\x39\x21\x01\x37"
+ "\x1d\x01\x34\x1a\x01\x32\x16\x01\x2f\x12\x01\x2d\x0f\x01\x2a\x0b"
+ "\x01\x27\x07\x01\x23\x01\x01\x1d\x01\x01\x17\x01\x01\x10\x01\x01"
+ "\x3d\x01\x01\x19\x19\x3f\x3f\x01\x01\x01\x01\x3f\x16\x16\x13\x10"
+ "\x10\x0f\x0d\x0d\x0b\x3c\x2e\x2a\x36\x27\x20\x30\x21\x18\x29\x1b"
+ "\x10\x3c\x39\x37\x37\x32\x2f\x31\x2c\x28\x2b\x26\x21\x30\x22\x20"
+)
+
+if __name__ == "__main__":
+ im = open("../hacks/sample.wal")
+ print im.info, im.mode, im.size
+ im.save("../out.png")
diff --git a/Imaging/PIL/WmfImagePlugin.py b/Imaging/PIL/WmfImagePlugin.py
new file mode 100644
index 0000000..2191160
--- /dev/null
+++ b/Imaging/PIL/WmfImagePlugin.py
@@ -0,0 +1,148 @@
+#
+# The Python Imaging Library
+# $Id: WmfImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# WMF stub codec
+#
+# history:
+# 1996-12-14 fl Created
+# 2004-02-22 fl Turned into a stub driver
+# 2004-02-23 fl Added EMF support
+#
+# Copyright (c) Secret Labs AB 1997-2004. All rights reserved.
+# Copyright (c) Fredrik Lundh 1996.
+#
+# See the README file for information on usage and redistribution.
+#
+
+__version__ = "0.2"
+
+import Image, ImageFile
+
+_handler = None
+
+##
+# Install application-specific WMF image handler.
+#
+# @param handler Handler object.
+
+def register_handler(handler):
+ global _handler
+ _handler = handler
+
+# --------------------------------------------------------------------
+
+def word(c, o=0):
+ return ord(c[o]) + (ord(c[o+1])<<8)
+
+def short(c, o=0):
+ v = ord(c[o]) + (ord(c[o+1])<<8)
+ if v >= 32768:
+ v = v - 65536
+ return v
+
+def dword(c, o=0):
+ return ord(c[o]) + (ord(c[o+1])<<8) + (ord(c[o+2])<<16) + (ord(c[o+3])<<24)
+
+def long(c, o=0):
+ return dword(c, o)
+
+#
+# --------------------------------------------------------------------
+# Read WMF file
+
+def _accept(prefix):
+ return (
+ prefix[:6] == "\xd7\xcd\xc6\x9a\x00\x00" or
+ prefix[:4] == "\x01\x00\x00\x00"
+ )
+
+##
+# Image plugin for Windows metafiles.
+
+class WmfStubImageFile(ImageFile.StubImageFile):
+
+ format = "WMF"
+ format_description = "Windows Metafile"
+
+ def _open(self):
+
+ # check placable header
+ s = self.fp.read(80)
+
+ if s[:6] == "\xd7\xcd\xc6\x9a\x00\x00":
+
+ # placeable windows metafile
+
+ # get units per inch
+ inch = word(s, 14)
+
+ # get bounding box
+ x0 = short(s, 6); y0 = short(s, 8)
+ x1 = short(s, 10); y1 = short(s, 12)
+
+ # normalize size to 72 dots per inch
+ size = (x1 - x0) * 72 / inch, (y1 - y0) * 72 / inch
+
+ self.info["wmf_bbox"] = x0, y0, x1, y1
+
+ self.info["dpi"] = 72
+
+ # print self.mode, self.size, self.info
+
+ # sanity check (standard metafile header)
+ if s[22:26] != "\x01\x00\t\x00":
+ raise SyntaxError("Unsupported WMF file format")
+
+ elif long(s) == 1 and s[40:44] == " EMF":
+ # enhanced metafile
+
+ # get bounding box
+ x0 = long(s, 8); y0 = long(s, 12)
+ x1 = long(s, 16); y1 = long(s, 20)
+
+ # get frame (in 0.01 millimeter units)
+ frame = long(s, 24), long(s, 28), long(s, 32), long(s, 36)
+
+ # normalize size to 72 dots per inch
+ size = x1 - x0, y1 - y0
+
+ # calculate dots per inch from bbox and frame
+ xdpi = 2540 * (x1 - y0) / (frame[2] - frame[0])
+ ydpi = 2540 * (y1 - y0) / (frame[3] - frame[1])
+
+ self.info["wmf_bbox"] = x0, y0, x1, y1
+
+ if xdpi == ydpi:
+ self.info["dpi"] = xdpi
+ else:
+ self.info["dpi"] = xdpi, ydpi
+
+ else:
+ raise SyntaxError("Unsupported file format")
+
+ self.mode = "RGB"
+ self.size = size
+
+ loader = self._load()
+ if loader:
+ loader.open(self)
+
+ def _load(self):
+ return _handler
+
+
+def _save(im, fp, filename):
+ if _handler is None or not hasattr("_handler", "save"):
+ raise IOError("WMF save handler not installed")
+ _handler.save(im, fp, filename)
+
+#
+# --------------------------------------------------------------------
+# Registry stuff
+
+Image.register_open(WmfStubImageFile.format, WmfStubImageFile, _accept)
+Image.register_save(WmfStubImageFile.format, _save)
+
+Image.register_extension(WmfStubImageFile.format, ".wmf")
+Image.register_extension(WmfStubImageFile.format, ".emf")
diff --git a/Imaging/PIL/XVThumbImagePlugin.py b/Imaging/PIL/XVThumbImagePlugin.py
new file mode 100644
index 0000000..4a9c0d6
--- /dev/null
+++ b/Imaging/PIL/XVThumbImagePlugin.py
@@ -0,0 +1,68 @@
+#
+# The Python Imaging Library.
+# $Id: XVThumbImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# XV Thumbnail file handler by Charles E. "Gene" Cash
+# (gcash@magicnet.net)
+#
+# see xvcolor.c and xvbrowse.c in the sources to John Bradley's XV,
+# available from ftp://ftp.cis.upenn.edu/pub/xv/
+#
+# history:
+# 98-08-15 cec created (b/w only)
+# 98-12-09 cec added color palette
+# 98-12-28 fl added to PIL (with only a few very minor modifications)
+#
+# To do:
+# FIXME: make save work (this requires quantization support)
+#
+
+__version__ = "0.1"
+
+import string
+import Image, ImageFile, ImagePalette
+
+# standard color palette for thumbnails (RGB332)
+PALETTE = ""
+for r in range(8):
+ for g in range(8):
+ for b in range(4):
+ PALETTE = PALETTE + (chr((r*255)/7)+chr((g*255)/7)+chr((b*255)/3))
+
+##
+# Image plugin for XV thumbnail images.
+
+class XVThumbImageFile(ImageFile.ImageFile):
+
+ format = "XVThumb"
+ format_description = "XV thumbnail image"
+
+ def _open(self):
+
+ # check magic
+ s = self.fp.read(6)
+ if s != "P7 332":
+ raise SyntaxError, "not an XV thumbnail file"
+
+ # skip info comments
+ while 1:
+ s = string.strip(self.fp.readline())
+ if s == "#END_OF_COMMENTS":
+ break
+
+ # read header line
+ s = string.split(self.fp.readline())
+
+ self.mode = "P"
+ self.size = int(s[0]), int(s[1])
+
+ self.palette = ImagePalette.raw("RGB", PALETTE)
+
+ self.tile = [
+ ("raw", (0, 0)+self.size,
+ self.fp.tell(), (self.mode, 0, 1)
+ )]
+
+# --------------------------------------------------------------------
+
+Image.register_open("XVThumb", XVThumbImageFile)
diff --git a/Imaging/PIL/XbmImagePlugin.py b/Imaging/PIL/XbmImagePlugin.py
new file mode 100644
index 0000000..a1dccea
--- /dev/null
+++ b/Imaging/PIL/XbmImagePlugin.py
@@ -0,0 +1,94 @@
+#
+# The Python Imaging Library.
+# $Id: XbmImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# XBM File handling
+#
+# History:
+# 1995-09-08 fl Created
+# 1996-11-01 fl Added save support
+# 1997-07-07 fl Made header parser more tolerant
+# 1997-07-22 fl Fixed yet another parser bug
+# 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.4)
+# 2001-05-13 fl Added hotspot handling (based on code from Bernhard Herzog)
+# 2004-02-24 fl Allow some whitespace before first #define
+#
+# Copyright (c) 1997-2004 by Secret Labs AB
+# Copyright (c) 1996-1997 by Fredrik Lundh
+#
+# See the README file for information on usage and redistribution.
+#
+
+__version__ = "0.6"
+
+import re, string
+import Image, ImageFile
+
+# XBM header
+xbm_head = re.compile(
+ "\s*#define[ \t]+[^_]*_width[ \t]+(?P<width>[0-9]+)[\r\n]+"
+ "#define[ \t]+[^_]*_height[ \t]+(?P<height>[0-9]+)[\r\n]+"
+ "(?P<hotspot>"
+ "#define[ \t]+[^_]*_x_hot[ \t]+(?P<xhot>[0-9]+)[\r\n]+"
+ "#define[ \t]+[^_]*_y_hot[ \t]+(?P<yhot>[0-9]+)[\r\n]+"
+ ")?"
+ "[\\000-\\377]*_bits\\[\\]"
+)
+
+def _accept(prefix):
+ return string.lstrip(prefix)[:7] == "#define"
+
+##
+# Image plugin for X11 bitmaps.
+
+class XbmImageFile(ImageFile.ImageFile):
+
+ format = "XBM"
+ format_description = "X11 Bitmap"
+
+ def _open(self):
+
+ m = xbm_head.match(self.fp.read(512))
+
+ if m:
+
+ xsize = int(m.group("width"))
+ ysize = int(m.group("height"))
+
+ if m.group("hotspot"):
+ self.info["hotspot"] = (
+ int(m.group("xhot")), int(m.group("yhot"))
+ )
+
+ self.mode = "1"
+ self.size = xsize, ysize
+
+ self.tile = [("xbm", (0, 0)+self.size, m.end(), None)]
+
+
+def _save(im, fp, filename):
+
+ if im.mode != "1":
+ raise IOError, "cannot write mode %s as XBM" % im.mode
+
+ fp.write("#define im_width %d\n" % im.size[0])
+ fp.write("#define im_height %d\n" % im.size[1])
+
+ hotspot = im.encoderinfo.get("hotspot")
+ if hotspot:
+ fp.write("#define im_x_hot %d\n" % hotspot[0])
+ fp.write("#define im_y_hot %d\n" % hotspot[1])
+
+ fp.write("static char im_bits[] = {\n")
+
+ ImageFile._save(im, fp, [("xbm", (0,0)+im.size, 0, None)])
+
+ fp.write("};\n")
+
+
+Image.register_open("XBM", XbmImageFile, _accept)
+Image.register_save("XBM", _save)
+
+Image.register_extension("XBM", ".xbm")
+
+Image.register_mime("XBM", "image/xbm")
diff --git a/Imaging/PIL/XpmImagePlugin.py b/Imaging/PIL/XpmImagePlugin.py
new file mode 100644
index 0000000..b8ac01f
--- /dev/null
+++ b/Imaging/PIL/XpmImagePlugin.py
@@ -0,0 +1,129 @@
+#
+# The Python Imaging Library.
+# $Id: XpmImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# XPM File handling
+#
+# History:
+# 1996-12-29 fl Created
+# 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.7)
+#
+# Copyright (c) Secret Labs AB 1997-2001.
+# Copyright (c) Fredrik Lundh 1996-2001.
+#
+# See the README file for information on usage and redistribution.
+#
+
+
+__version__ = "0.2"
+
+
+import re, string
+import Image, ImageFile, ImagePalette
+
+# XPM header
+xpm_head = re.compile("\"([0-9]*) ([0-9]*) ([0-9]*) ([0-9]*)")
+
+
+def _accept(prefix):
+ return prefix[:9] == "/* XPM */"
+
+##
+# Image plugin for X11 pixel maps.
+
+class XpmImageFile(ImageFile.ImageFile):
+
+ format = "XPM"
+ format_description = "X11 Pixel Map"
+
+ def _open(self):
+
+ if not _accept(self.fp.read(9)):
+ raise SyntaxError, "not an XPM file"
+
+ # skip forward to next string
+ while 1:
+ s = self.fp.readline()
+ if not s:
+ raise SyntaxError, "broken XPM file"
+ m = xpm_head.match(s)
+ if m:
+ break
+
+ self.size = int(m.group(1)), int(m.group(2))
+
+ pal = int(m.group(3))
+ bpp = int(m.group(4))
+
+ if pal > 256 or bpp != 1:
+ raise ValueError, "cannot read this XPM file"
+
+ #
+ # load palette description
+
+ palette = ["\0\0\0"] * 256
+
+ for i in range(pal):
+
+ s = self.fp.readline()
+ if s[-2:] == '\r\n':
+ s = s[:-2]
+ elif s[-1:] in '\r\n':
+ s = s[:-1]
+
+ c = ord(s[1])
+ s = string.split(s[2:-2])
+
+ for i in range(0, len(s), 2):
+
+ if s[i] == "c":
+
+ # process colour key
+ rgb = s[i+1]
+ if rgb == "None":
+ self.info["transparency"] = c
+ elif rgb[0] == "#":
+ # FIXME: handle colour names (see ImagePalette.py)
+ rgb = string.atoi(rgb[1:], 16)
+ palette[c] = chr((rgb >> 16) & 255) +\
+ chr((rgb >> 8) & 255) +\
+ chr(rgb & 255)
+ else:
+ # unknown colour
+ raise ValueError, "cannot read this XPM file"
+ break
+
+ else:
+
+ # missing colour key
+ raise ValueError, "cannot read this XPM file"
+
+ self.mode = "P"
+ self.palette = ImagePalette.raw("RGB", string.join(palette, ""))
+
+ self.tile = [("raw", (0, 0)+self.size, self.fp.tell(), ("P", 0, 1))]
+
+ def load_read(self, bytes):
+
+ #
+ # load all image data in one chunk
+
+ xsize, ysize = self.size
+
+ s = [None] * ysize
+
+ for i in range(ysize):
+ s[i] = string.ljust(self.fp.readline()[1:xsize+1], xsize)
+
+ self.fp = None
+
+ return string.join(s, "")
+
+#
+# Registry
+
+Image.register_open("XPM", XpmImageFile, _accept)
+
+Image.register_extension("XPM", ".xpm")
+
+Image.register_mime("XPM", "image/xpm")
diff --git a/Imaging/PIL/__init__.py b/Imaging/PIL/__init__.py
new file mode 100644
index 0000000..3290883
--- /dev/null
+++ b/Imaging/PIL/__init__.py
@@ -0,0 +1,12 @@
+#
+# The Python Imaging Library.
+# $Id: __init__.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# package placeholder
+#
+# Copyright (c) 1999 by Secret Labs AB.
+#
+# See the README file for information on usage and redistribution.
+#
+
+# ;-)
diff --git a/Imaging/README b/Imaging/README
new file mode 100644
index 0000000..46a53de
--- /dev/null
+++ b/Imaging/README
@@ -0,0 +1,270 @@
+The Python Imaging Library
+$Id: README 2939 2006-12-03 13:43:51Z fredrik $
+
+Release 1.1.6 (December 3, 2006)
+
+====================================================================
+The Python Imaging Library 1.1.6
+====================================================================
+
+Contents
+--------
+
++ Introduction
++ Support Options
+ - Commercial support
+ - Free support
++ Software License
++ Build instructions (all platforms)
+ - Additional notes for Mac OS X
+ - Additional notes for Windows
+
+--------------------------------------------------------------------
+Introduction
+--------------------------------------------------------------------
+
+The Python Imaging Library (PIL) adds image processing capabilities
+to your Python environment. This library provides extensive file
+format support, an efficient internal representation, and powerful
+image processing capabilities.
+
+This source kit has been built and tested on Windows NT/2000/XP, Mac
+OS X, and most major Unix platforms (including Alpha, Solaris, and
+Intel systems). We believe that it should work on most modern
+platforms (people are using it on Crays, after all ;-)
+
+The main distribution site for this software is:
+
+ http://www.pythonware.com/products/pil/
+
+That site also contains information about free and commercial support
+options, PIL add-ons, answers to frequently asked questions, and more.
+
+
+Development versions (alphas, betas) are available here:
+
+ http://effbot.org/downloads/
+
+
+The PIL handbook is not included in this distribution; to get the
+latest version, check:
+
+ http://www.pythonware.com/library/
+ http://effbot.org/books/imagingbook/ (drafts)
+
+
+For installation and licensing details, see below.
+
+
+--------------------------------------------------------------------
+Support Options
+--------------------------------------------------------------------
+
++ Commercial Support
+
+Secret Labs (PythonWare) offers support contracts for companies using
+the Python Imaging Library in commercial applications, and in mission-
+critical environments. The support contract includes technical support,
+bug fixes, extensions to the PIL library, sample applications, and more.
+
+For the full story, check:
+
+ http://www.pythonware.com/products/pil/support.htm
+
+
++ Free Support
+
+For support and general questions on the Python Imaging Library, send
+e-mail to the Image SIG mailing list:
+
+ image-sig@python.org
+
+You can join the Image SIG by sending a mail to:
+
+ image-sig-request@python.org
+
+Put "subscribe" in the message body to automatically subscribe to the
+list, or "help" to get additional information. Alternatively, you can
+send your questions to the Python mailing list, python-list@python.org,
+or post them to the newsgroup comp.lang.python. DO NOT SEND SUPPORT
+QUESTIONS TO PYTHONWARE ADDRESSES.
+
+
+--------------------------------------------------------------------
+Software License
+--------------------------------------------------------------------
+
+The Python Imaging Library is
+
+Copyright (c) 1997-2006 by Secret Labs AB
+Copyright (c) 1995-2006 by Fredrik Lundh
+
+By obtaining, using, and/or copying this software and/or its
+associated documentation, you agree that you have read, understood,
+and will comply with the following terms and conditions:
+
+Permission to use, copy, modify, and distribute this software and its
+associated documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies, and that both that copyright notice and this permission notice
+appear in supporting documentation, and that the name of Secret Labs
+AB or the author not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+--------------------------------------------------------------------
+Build instructions (all platforms)
+--------------------------------------------------------------------
+
+For a list of changes in this release, see the CHANGES document.
+
+0. If you're in a hurry, try this:
+
+ $ gunzip Imaging-1.1.6.tar.gz
+ $ tar xvf Imaging-1.1.6.tar
+ $ cd Imaging-1.1.6
+ $ python setup.py install
+
+ If you prefer to know what you're doing, read on.
+
+
+1. Prerequisites.
+
+ If you need any of the features described below, make sure you
+ have the necessary libraries before building PIL.
+
+ feature library
+ -----------------------------------------------------------------
+ JPEG support libjpeg (6a or 6b)
+
+ http://www.ijg.org
+ http://www.ijg.org/files/jpegsrc.v6b.tar.gz
+ ftp://ftp.uu.net/graphics/jpeg/
+
+ PNG support zlib (1.2.3 or later is recommended)
+
+ http://www.gzip.org/zlib/
+
+ OpenType/TrueType freetype2 (2.1.3 or later is recommended)
+ support
+ http://www.freetype.org
+ http://freetype.sourceforge.net
+
+ If you have a recent Linux version, the libraries provided with
+ the operating system usually work just fine. If some library is
+ missing, installing a prebuilt version (jpeg-devel, zlib-devel,
+ etc) is usually easier than building from source.
+
+ If you're using Mac OS X, you can use the 'fink' tool to install
+ missing libraries (also see the Mac OS X section below).
+
+ Similar tools are available for many other platforms (such as
+ 'apt-get' for Debian).
+
+
+2. To build under Python 1.5.2, you need to install the stand-alone
+ version of the distutils library:
+
+ http://www.python.org/sigs/distutils-sig/download.html
+
+ For newer releases, the distutils library is included in the
+ Python standard library.
+
+
+3. If you didn't build Python from sources, make sure you have
+ Python's build support files on your machine. If you've down-
+ loaded a prebuilt package (e.g. a Linux RPM), you probably
+ need additional developer packages. Look for packages named
+ "python-devel", "py-dev", or similar.
+
+
+4. When you have everything you need, unpack the PIL distribution
+ (the file Imaging-1.1.6.tar.gz) in your Python extensions
+ directory (if you have one, that is. If not, feel free to
+ unpack it in any other suitable directory).
+
+ $ cd Python-2.4/Extensions # example
+ $ gunzip Imaging-1.1.6.tar.gz
+ $ tar xvf Imaging-1.1.6.tar
+
+
+5. Build the library. We recommend that you do an in-place build,
+ and run the self test before installing.
+
+ $ cd Imaging-1.1.6
+ $ python setup.py build_ext -i
+ $ python selftest.py
+
+ When the build finishes, a summary report is shown. Make sure
+ that the optional components you need are included.
+
+ ----------------------------------------------------------------
+ PIL 1.1.6 BUILD SUMMARY
+ ----------------------------------------------------------------
+ *** TKINTER support not available (Tcl/Tk 8.3 libraries needed)
+ --- JPEG support ok
+ --- ZLIB (PNG/ZIP) support ok
+ --- FREETYPE support ok
+ ----------------------------------------------------------------
+
+ If the build script won't find a given component, you can edit the
+ setup.py file and set the appropriate ROOT variable. For details,
+ see instructions in the file.
+
+
+6. If the setup.py and selftest.py commands finish without any
+ errors, you're ready to install the library:
+
+ $ python setup.py install
+
+ (depending on how Python has been installed on your machine,
+ you might have to log in as a superuser to run the 'install'
+ command.)
+
+
+--------------------------------------------------------------------
+Additional notes for Mac OS X
+--------------------------------------------------------------------
+
+On Mac OS X you will usually install additional software such as
+libjpeg or freetype with the "fink" tool, and then it ends up in
+"/sw". If you have installed the libraries elsewhere, you may have
+to tweak the "setup.py" file before building.
+
+
+--------------------------------------------------------------------
+Additional notes for Windows
+--------------------------------------------------------------------
+
+On Windows, you need to tweak the ROOT settings in the "setup.py"
+file, to make it find the external libraries. See comments in the
+file for details.
+
+Make sure to build PIL and the external libraries with the same
+runtime linking options as was used for the Python interpreter
+(usually /MD, under Visual Studio).
+
+
+Note that most Python distributions include libraries compiled for
+Microsoft Visual Studio. To build extensions using other tool chains,
+see the "Using non-Microsoft compilers on Windows" section in the
+distutils handbook:
+
+ http://www.python.org/doc/current/inst/non-ms-compilers.html
+
+For additional information on how to build extensions using the
+popular MinGW compiler, see:
+
+ http://mingw.org (compiler)
+ http://sebsauvage.net/python/mingw.html (build instructions)
+ http://sourceforge.net/projects/gnuwin32 (prebuilt libraries)
+
diff --git a/Imaging/Sane/CHANGES b/Imaging/Sane/CHANGES
new file mode 100644
index 0000000..95c1469
--- /dev/null
+++ b/Imaging/Sane/CHANGES
@@ -0,0 +1,34 @@
+
+from V1.0 to V2.0
+
+_sane.c:
+ - Values for option constraints are correctly translated to floats
+ if value type is TYPE_FIXED for SANE_CONSTRAINT_RANGE and
+ SANE_CONSTRAINT_WORD_LIST
+ - added constants INFO_INEXACT, INFO_RELOAD_OPTIONS,
+ INFO_RELOAD_PARAMS (possible return values of set_option())
+ to module dictionnary.
+ - removed additional return variable 'i' from SaneDev_get_option(),
+ because it is only set when SANE_ACTION_SET_VALUE is used.
+ - scanDev.get_parameters() now returns the scanner mode as 'format',
+ no more the typical PIL codes. So 'L' became 'gray', 'RGB' is now
+ 'color', 'R' is 'red', 'G' is 'green', 'B' is 'red'. This matches
+ the way scanDev.mode is set.
+ This should be the only incompatibility vs. version 1.0.
+
+sane.py
+ - ScanDev got new method __load_option_dict() called from __init__()
+ and from __setattr__() if backend reported that the frontend should
+ reload the options.
+ - Nice human-readable __repr__() method added for class Option
+ - if __setattr__ (i.e. set_option) reports that all other options
+ have to be reloaded due to a change in the backend then they are reloaded.
+ - due to the change in SaneDev_get_option() only the 'value' is
+ returned from get_option().
+ - in __setattr__ integer values are automatically converted to floats
+ if SANE backend expects SANE_FIXED (i.e. fix-point float)
+ - The scanner options can now directly be accessed via scanDev[optionName]
+ instead scanDev.opt[optionName]. (The old way still works).
+
+V1.0:
+ A.M. Kuchling's original pysane package. \ No newline at end of file
diff --git a/Imaging/Sane/README b/Imaging/Sane/README
new file mode 100644
index 0000000..ddff0cf
--- /dev/null
+++ b/Imaging/Sane/README
@@ -0,0 +1,22 @@
+
+Python SANE module V1.1 (30 Sep. 2004)
+
+The SANE module provides an interface to the SANE scanner and frame
+grabber interface for Linux. This module was contributed by Andrew
+Kuchling and is extended and currently maintained by Ralph Heinkel
+(rheinkel-at-email.de). If you write to me please make sure to have the
+word 'SANE' or 'sane' in the subject of your mail, otherwise it might
+be classified as spam in the future.
+
+
+To build this module, type (in the Sane directory):
+
+ python setup.py build
+
+In order to install the module type:
+
+ python setup.py install
+
+
+For some basic documentation please look at the file sanedoc.txt
+The two demo_*.py scripts give basic examples on how to use the software.
diff --git a/Imaging/Sane/_sane.c b/Imaging/Sane/_sane.c
new file mode 100644
index 0000000..21e542f
--- /dev/null
+++ b/Imaging/Sane/_sane.c
@@ -0,0 +1,1325 @@
+/***********************************************************
+(C) Copyright 2003 A.M. Kuchling. All Rights Reserved
+(C) Copyright 2004 A.M. Kuchling, Ralph Heinkel All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of A.M. Kuchling and
+Ralph Heinkel not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+A.M. KUCHLING, R.H. HEINKEL DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* SaneDev objects */
+
+#include "Python.h"
+#include "Imaging.h"
+#include <sane/sane.h>
+
+#include <sys/time.h>
+
+static PyObject *ErrorObject;
+
+typedef struct {
+ PyObject_HEAD
+ SANE_Handle h;
+} SaneDevObject;
+
+#ifdef WITH_THREAD
+PyThreadState *_save;
+#endif
+
+/* Raise a SANE exception */
+PyObject *
+PySane_Error(SANE_Status st)
+{
+ const char *string;
+
+ if (st==SANE_STATUS_GOOD) {Py_INCREF(Py_None); return (Py_None);}
+ string=sane_strstatus(st);
+ PyErr_SetString(ErrorObject, string);
+ return NULL;
+}
+
+staticforward PyTypeObject SaneDev_Type;
+
+#define SaneDevObject_Check(v) ((v)->ob_type == &SaneDev_Type)
+
+static SaneDevObject *
+newSaneDevObject(void)
+{
+ SaneDevObject *self;
+ self = PyObject_NEW(SaneDevObject, &SaneDev_Type);
+ if (self == NULL)
+ return NULL;
+ self->h=NULL;
+ return self;
+}
+
+/* SaneDev methods */
+
+static void
+SaneDev_dealloc(SaneDevObject *self)
+{
+ if (self->h) sane_close(self->h);
+ self->h=NULL;
+ PyObject_DEL(self);
+}
+
+static PyObject *
+SaneDev_close(SaneDevObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ if (self->h) sane_close(self->h);
+ self->h=NULL;
+ Py_INCREF(Py_None);
+ return (Py_None);
+}
+
+static PyObject *
+SaneDev_get_parameters(SaneDevObject *self, PyObject *args)
+{
+ SANE_Status st;
+ SANE_Parameters p;
+ char *format="unknown format";
+
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ if (self->h==NULL)
+ {
+ PyErr_SetString(ErrorObject, "SaneDev object is closed");
+ return NULL;
+ }
+ Py_BEGIN_ALLOW_THREADS
+ st=sane_get_parameters(self->h, &p);
+ Py_END_ALLOW_THREADS
+
+ if (st) return PySane_Error(st);
+ switch (p.format)
+ {
+ case(SANE_FRAME_GRAY): format="gray"; break;
+ case(SANE_FRAME_RGB): format="color"; break;
+ case(SANE_FRAME_RED): format="red"; break;
+ case(SANE_FRAME_GREEN): format="green"; break;
+ case(SANE_FRAME_BLUE): format="blue"; break;
+ }
+
+ return Py_BuildValue("si(ii)ii", format, p.last_frame, p.pixels_per_line,
+ p.lines, p.depth, p.bytes_per_line);
+}
+
+
+static PyObject *
+SaneDev_fileno(SaneDevObject *self, PyObject *args)
+{
+ SANE_Status st;
+ SANE_Int fd;
+
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ if (self->h==NULL)
+ {
+ PyErr_SetString(ErrorObject, "SaneDev object is closed");
+ return NULL;
+ }
+ st=sane_get_select_fd(self->h, &fd);
+ if (st) return PySane_Error(st);
+ return PyInt_FromLong(fd);
+}
+
+static PyObject *
+SaneDev_start(SaneDevObject *self, PyObject *args)
+{
+ SANE_Status st;
+
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ if (self->h==NULL)
+ {
+ PyErr_SetString(ErrorObject, "SaneDev object is closed");
+ return NULL;
+ }
+ /* sane_start can take several seconds, if the user initiates
+ a new scan, while the scan head of a flatbed scanner moves
+ back to the start position after finishing a previous scan.
+ Hence it is worth to allow threads here.
+ */
+ Py_BEGIN_ALLOW_THREADS
+ st=sane_start(self->h);
+ Py_END_ALLOW_THREADS
+ if (st) return PySane_Error(st);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+SaneDev_cancel(SaneDevObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ if (self->h==NULL)
+ {
+ PyErr_SetString(ErrorObject, "SaneDev object is closed");
+ return NULL;
+ }
+ sane_cancel(self->h);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+SaneDev_get_options(SaneDevObject *self, PyObject *args)
+{
+ const SANE_Option_Descriptor *d;
+ PyObject *list, *value;
+ int i=1;
+
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ if (self->h==NULL)
+ {
+ PyErr_SetString(ErrorObject, "SaneDev object is closed");
+ return NULL;
+ }
+ if (!(list = PyList_New(0)))
+ return NULL;
+
+ do
+ {
+ d=sane_get_option_descriptor(self->h, i);
+ if (d!=NULL)
+ {
+ PyObject *constraint=NULL;
+ int j;
+
+ switch (d->constraint_type)
+ {
+ case(SANE_CONSTRAINT_NONE):
+ Py_INCREF(Py_None); constraint=Py_None; break;
+ case(SANE_CONSTRAINT_RANGE):
+ if (d->type == SANE_TYPE_INT)
+ constraint=Py_BuildValue("iii", d->constraint.range->min,
+ d->constraint.range->max,
+ d->constraint.range->quant);
+ else
+ constraint=Py_BuildValue("ddd",
+ SANE_UNFIX(d->constraint.range->min),
+ SANE_UNFIX(d->constraint.range->max),
+ SANE_UNFIX(d->constraint.range->quant));
+ break;
+ case(SANE_CONSTRAINT_WORD_LIST):
+ constraint=PyList_New(d->constraint.word_list[0]);
+ if (d->type == SANE_TYPE_INT)
+ for (j=1; j<=d->constraint.word_list[0]; j++)
+ PyList_SetItem(constraint, j-1,
+ PyInt_FromLong(d->constraint.word_list[j]));
+ else
+ for (j=1; j<=d->constraint.word_list[0]; j++)
+ PyList_SetItem(constraint, j-1,
+ PyFloat_FromDouble(SANE_UNFIX(d->constraint.word_list[j])));
+ break;
+ case(SANE_CONSTRAINT_STRING_LIST):
+ constraint=PyList_New(0);
+ for(j=0; d->constraint.string_list[j]!=NULL; j++)
+ PyList_Append(constraint,
+ PyString_FromString(d->constraint.string_list[j]));
+ break;
+ }
+ value=Py_BuildValue("isssiiiiO", i, d->name, d->title, d->desc,
+ d->type, d->unit, d->size, d->cap, constraint);
+ PyList_Append(list, value);
+ }
+ i++;
+ } while (d!=NULL);
+ return list;
+}
+
+static PyObject *
+SaneDev_get_option(SaneDevObject *self, PyObject *args)
+{
+ SANE_Status st;
+ const SANE_Option_Descriptor *d;
+ PyObject *value=NULL;
+ int n;
+ void *v;
+
+ if (!PyArg_ParseTuple(args, "i", &n))
+ {
+ return NULL;
+ }
+ if (self->h==NULL)
+ {
+ PyErr_SetString(ErrorObject, "SaneDev object is closed");
+ return NULL;
+ }
+ d=sane_get_option_descriptor(self->h, n);
+ v=malloc(d->size+1);
+ st=sane_control_option(self->h, n, SANE_ACTION_GET_VALUE,
+ v, NULL);
+
+ if (st)
+ {
+ free(v);
+ return PySane_Error(st);
+ }
+
+ switch(d->type)
+ {
+ case(SANE_TYPE_BOOL):
+ case(SANE_TYPE_INT):
+ value=Py_BuildValue("i", *( (SANE_Int*)v) );
+ break;
+ case(SANE_TYPE_FIXED):
+ value=Py_BuildValue("d", SANE_UNFIX((*((SANE_Fixed*)v))) );
+ break;
+ case(SANE_TYPE_STRING):
+ value=Py_BuildValue("s", v);
+ break;
+ case(SANE_TYPE_BUTTON):
+ case(SANE_TYPE_GROUP):
+ value=Py_BuildValue("O", Py_None);
+ break;
+ }
+
+ free(v);
+ return value;
+}
+
+static PyObject *
+SaneDev_set_option(SaneDevObject *self, PyObject *args)
+{
+ SANE_Status st;
+ const SANE_Option_Descriptor *d;
+ SANE_Int i;
+ PyObject *value;
+ int n;
+ void *v;
+
+ if (!PyArg_ParseTuple(args, "iO", &n, &value))
+ return NULL;
+ if (self->h==NULL)
+ {
+ PyErr_SetString(ErrorObject, "SaneDev object is closed");
+ return NULL;
+ }
+ d=sane_get_option_descriptor(self->h, n);
+ v=malloc(d->size+1);
+
+ switch(d->type)
+ {
+ case(SANE_TYPE_BOOL):
+ if (!PyInt_Check(value))
+ {
+ PyErr_SetString(PyExc_TypeError, "SANE_BOOL requires an integer");
+ free(v);
+ return NULL;
+ }
+ /* fall through */
+ case(SANE_TYPE_INT):
+ if (!PyInt_Check(value))
+ {
+ PyErr_SetString(PyExc_TypeError, "SANE_INT requires an integer");
+ free(v);
+ return NULL;
+ }
+ *( (SANE_Int*)v) = PyInt_AsLong(value);
+ break;
+ case(SANE_TYPE_FIXED):
+ if (!PyFloat_Check(value))
+ {
+ PyErr_SetString(PyExc_TypeError, "SANE_FIXED requires a floating point number");
+ free(v);
+ return NULL;
+ }
+ *( (SANE_Fixed*)v) = SANE_FIX(PyFloat_AsDouble(value));
+ break;
+ case(SANE_TYPE_STRING):
+ if (!PyString_Check(value))
+ {
+ PyErr_SetString(PyExc_TypeError, "SANE_STRING requires a string");
+ free(v);
+ return NULL;
+ }
+ strncpy(v, PyString_AsString(value), d->size-1);
+ ((char*)v)[d->size-1] = 0;
+ break;
+ case(SANE_TYPE_BUTTON):
+ case(SANE_TYPE_GROUP):
+ break;
+ }
+
+ st=sane_control_option(self->h, n, SANE_ACTION_SET_VALUE,
+ v, &i);
+ if (st) {free(v); return PySane_Error(st);}
+
+ free(v);
+ return Py_BuildValue("i", i);
+}
+
+static PyObject *
+SaneDev_set_auto_option(SaneDevObject *self, PyObject *args)
+{
+ SANE_Status st;
+ const SANE_Option_Descriptor *d;
+ SANE_Int i;
+ int n;
+
+ if (!PyArg_ParseTuple(args, "i", &n))
+ return NULL;
+ if (self->h==NULL)
+ {
+ PyErr_SetString(ErrorObject, "SaneDev object is closed");
+ return NULL;
+ }
+ d=sane_get_option_descriptor(self->h, n);
+ st=sane_control_option(self->h, n, SANE_ACTION_SET_AUTO,
+ NULL, &i);
+ if (st) {return PySane_Error(st);}
+
+ return Py_BuildValue("i", i);
+ }
+
+#define READSIZE 32768
+
+static PyObject *
+SaneDev_snap(SaneDevObject *self, PyObject *args)
+{
+ SANE_Status st;
+ /* The buffer should be a multiple of 3 in size, so each sane_read
+ operation will return an integral number of RGB triples. */
+ SANE_Byte buffer[READSIZE]; /* XXX how big should the buffer be? */
+ SANE_Int len, lastlen;
+ Imaging im;
+ SANE_Parameters p;
+ int px, py, remain, cplen, bufpos, padbytes;
+ long L;
+ char errmsg[80];
+ union
+ { char c[2];
+ INT16 i16;
+ }
+ endian;
+ PyObject *pyNoCancel = NULL;
+ int noCancel = 0;
+
+ endian.i16 = 1;
+
+ if (!PyArg_ParseTuple(args, "l|O", &L, &pyNoCancel))
+ return NULL;
+ if (self->h==NULL)
+ {
+ PyErr_SetString(ErrorObject, "SaneDev object is closed");
+ return NULL;
+ }
+ im=(Imaging)L;
+
+ if (pyNoCancel)
+ noCancel = PyObject_IsTrue(pyNoCancel);
+
+ st=SANE_STATUS_GOOD; px=py=0;
+ /* xxx not yet implemented
+ - handscanner support (i.e., unknown image length during start)
+ - generally: move the functionality from method snap in sane.py
+ down here -- I don't like this cross-dependency.
+ we need to call sane_get_parameters here, and we can create
+ the result Image object here.
+ */
+
+ Py_UNBLOCK_THREADS
+ sane_get_parameters(self->h, &p);
+ if (p.format == SANE_FRAME_GRAY)
+ {
+ switch (p.depth)
+ {
+ case 1:
+ remain = p.bytes_per_line * im->ysize;
+ padbytes = p.bytes_per_line - (im->xsize+7)/8;
+ bufpos = 0;
+ lastlen = len = 0;
+ while (st!=SANE_STATUS_EOF && py < im->ysize)
+ {
+ while (len > 0 && py < im->ysize)
+ {
+ int i, j, k;
+ j = buffer[bufpos++];
+ k = 0x80;
+ for (i = 0; i < 8 && px < im->xsize; i++)
+ {
+ im->image8[py][px++] = (k&j) ? 0 : 0xFF;
+ k = k >> 1;
+ }
+ len--;
+ if (px >= im->xsize)
+ {
+ bufpos += padbytes;
+ len -= padbytes;
+ py++;
+ px = 0;
+ }
+ }
+ st=sane_read(self->h, buffer,
+ remain<READSIZE ? remain : READSIZE, &len);
+ if (st && (st!=SANE_STATUS_EOF))
+ {
+ sane_cancel(self->h);
+ Py_BLOCK_THREADS
+ return PySane_Error(st);
+ }
+ bufpos -= lastlen;
+ lastlen = len;
+ remain -= len;
+ /* skip possible pad bytes at the start of the buffer */
+ len -= bufpos;
+ }
+ break;
+ case 8:
+ remain = p.bytes_per_line * im->ysize;
+ padbytes = p.bytes_per_line - im->xsize;
+ bufpos = 0;
+ len = 0;
+ while (st!=SANE_STATUS_EOF && py < im->ysize)
+ {
+ while (len > 0 && py < im->ysize)
+ {
+ cplen = len;
+ if (px + cplen >= im->xsize)
+ cplen = im->xsize - px;
+ memcpy(&im->image8[py][px], &buffer[bufpos], cplen);
+ len -= cplen;
+ bufpos += cplen;
+ px += cplen;
+ if (px >= im->xsize)
+ {
+ px = 0;
+ py++;
+ bufpos += padbytes;
+ len -= padbytes;
+ }
+ }
+ bufpos = -len;
+
+ st=sane_read(self->h, buffer,
+ remain<READSIZE ? remain : READSIZE, &len);
+ if (st && (st!=SANE_STATUS_EOF))
+ {
+ sane_cancel(self->h);
+ Py_BLOCK_THREADS
+ return PySane_Error(st);
+ }
+ remain -= len;
+ len -= bufpos;
+ }
+ break;
+ case 16:
+ remain = p.bytes_per_line * im->ysize;
+ padbytes = p.bytes_per_line - 2 * im->xsize;
+ bufpos = endian.c[0];
+ lastlen = len = 0;
+ while (st!=SANE_STATUS_EOF && py < im->ysize)
+ {
+ while (len > 0 && py < im->ysize)
+ {
+ im->image8[py][px++] = buffer[bufpos];
+ bufpos += 2;
+ len -= 2;
+ if (px >= im->xsize)
+ {
+ bufpos += padbytes;
+ len -= padbytes;
+ py++;
+ px = 0;
+ }
+ }
+ st=sane_read(self->h, buffer,
+ remain<READSIZE ? remain : READSIZE, &len);
+ if (st && (st!=SANE_STATUS_EOF))
+ {
+ sane_cancel(self->h);
+ Py_BLOCK_THREADS
+ return PySane_Error(st);
+ }
+ remain -= len;
+ bufpos -= lastlen;
+ lastlen = len;
+ len -= bufpos;
+ }
+ break;
+ default:
+ /* other depths are not formally "illegal" according to the
+ Sane API, but it's agreed by Sane developers that other
+ depths than 1, 8, 16 should not be used
+ */
+ sane_cancel(self->h);
+ Py_BLOCK_THREADS
+ snprintf(errmsg, 80, "unsupported pixel depth: %i", p.depth);
+ PyErr_SetString(ErrorObject, errmsg);
+ return NULL;
+ }
+ }
+ else if (p.format == SANE_FRAME_RGB)
+ {
+ int incr, color, pxs, pxmax, bit, val, mask;
+ switch (p.depth)
+ {
+ case 1:
+ remain = p.bytes_per_line * im->ysize;
+ padbytes = p.bytes_per_line - ((im->xsize+7)/8) * 3;
+ bufpos = 0;
+ len = 0;
+ lastlen = 0;
+ pxmax = 4 * im->xsize;
+ while (st!=SANE_STATUS_EOF && py < im->ysize)
+ {
+ pxs = px;
+ for (color = 0; color < 3; color++)
+ {
+ while (len <= 0 && st == SANE_STATUS_GOOD)
+ {
+ st=sane_read(self->h, buffer,
+ remain<READSIZE ? remain : READSIZE, &len);
+ if (st && (st!=SANE_STATUS_EOF))
+ {
+ sane_cancel(self->h);
+ Py_BLOCK_THREADS
+ return PySane_Error(st);
+ }
+ bufpos -= lastlen;
+ remain -= len;
+ lastlen = len;
+ /* skip possible pad bytes at the start of the buffer */
+ len -= bufpos;
+ }
+ if (st == SANE_STATUS_EOF) break;
+ pxs = px;
+ val = buffer[bufpos++];
+ len--;
+ mask = 0x80;
+ for (bit = 0; (bit < 8) && (px < pxmax); bit++)
+ {
+ ((UINT8**)(im->image32))[py][px] = (val&mask) ? 0xFF : 0;
+ mask = mask >> 1;
+ px += 4;
+ }
+ pxs++;
+ px = pxs;
+ }
+ if (st == SANE_STATUS_EOF)
+ break;
+ for (bit = 0; bit < 8 && px < pxmax; bit++)
+ {
+ ((UINT8**)(im->image32))[py][px] = 0;
+ px += 4;
+ }
+ px -= 3;
+ if (px >= pxmax)
+ {
+ bufpos += padbytes;
+ len -= padbytes;
+ py++;
+ px = 0;
+ }
+ }
+ break;
+ case 8:
+ case 16:
+ if (p.depth == 8)
+ {
+ padbytes = p.bytes_per_line - 3 * im->xsize;
+ bufpos = 0;
+ incr = 1;
+ }
+ else
+ {
+ padbytes = p.bytes_per_line - 6 * im->xsize;
+ bufpos = endian.c[0];
+ incr = 2;
+ }
+ remain = p.bytes_per_line * im->ysize;
+ len = 0;
+ lastlen = 0;
+ pxmax = 4 * im->xsize;
+ /* probably not very efficient. But we have to deal with these
+ possible conditions:
+ - we may have padding bytes at the end of a scan line
+ - the number of bytes read with sane_read may be smaller
+ than the number of pad bytes
+ - the buffer may become empty after setting any of the
+ red/green/blue pixel values
+
+ */
+ while (st != SANE_STATUS_EOF && py < im->ysize)
+ {
+ for (color = 0; color < 3; color++)
+ {
+ while (len <= 0 && st == SANE_STATUS_GOOD)
+ {
+ bufpos -= lastlen;
+ if (remain == 0)
+ {
+ sane_cancel(self->h);
+ Py_BLOCK_THREADS
+ PyErr_SetString(ErrorObject, "internal _sane error: premature end of scan");
+ return NULL;
+ }
+ st = sane_read(self->h, buffer,
+ remain<(READSIZE) ? remain : (READSIZE), &len);
+ if (st && (st!=SANE_STATUS_EOF))
+ {
+ sane_cancel(self->h);
+ Py_BLOCK_THREADS
+ return PySane_Error(st);
+ }
+ lastlen = len;
+ remain -= len;
+ len -= bufpos;
+ }
+ if (st == SANE_STATUS_EOF) break;
+ ((UINT8**)(im->image32))[py][px++] = buffer[bufpos];
+ bufpos += incr;
+ len -= incr;
+ }
+ if (st == SANE_STATUS_EOF) break;
+
+ ((UINT8**)(im->image32))[py][px++] = 0;
+
+ if (px >= pxmax)
+ {
+ px = 0;
+ py++;
+ bufpos += padbytes;
+ len -= padbytes;
+ }
+ }
+ break;
+ default:
+ Py_BLOCK_THREADS
+ sane_cancel(self->h);
+ snprintf(errmsg, 80, "unsupported pixel depth: %i", p.depth);
+ PyErr_SetString(ErrorObject, errmsg);
+ return NULL;
+ }
+
+ }
+ else /* should be SANE_FRAME_RED, GREEN or BLUE */
+ {
+ int lastlen, pxa, pxmax, offset, incr, frame_count = 0;
+ /* at least the Sane test backend behaves a bit weird, if
+ it returns "premature EOF" for sane_read, i.e., if the
+ option "return value of sane_read" is set to SANE_STATUS_EOF.
+ In this case, the test backend does not advance to the next frame,
+ so p.last_frame will never be set...
+ So let's count the number of frames we try to acquire
+ */
+ while (!p.last_frame && frame_count < 4)
+ {
+ frame_count++;
+ st = sane_get_parameters(self->h, &p);
+ if (st)
+ {
+ sane_cancel(self->h);
+ Py_BLOCK_THREADS
+ return PySane_Error(st);
+ }
+ remain = p.bytes_per_line * im->ysize;
+ bufpos = 0;
+ len = 0;
+ lastlen = 0;
+ py = 0;
+ switch (p.format)
+ {
+ case SANE_FRAME_RED:
+ offset = 0;
+ break;
+ case SANE_FRAME_GREEN:
+ offset = 1;
+ break;
+ case SANE_FRAME_BLUE:
+ offset = 2;
+ break;
+ default:
+ sane_cancel(self->h);
+ Py_BLOCK_THREADS
+ snprintf(errmsg, 80, "unknown/invalid frame format: %i", p.format);
+ PyErr_SetString(ErrorObject, errmsg);
+ return NULL;
+ }
+ px = offset;
+ pxa = 3;
+ pxmax = im->xsize * 4;
+ switch (p.depth)
+ {
+ case 1:
+ padbytes = p.bytes_per_line - (im->xsize+7)/8;
+ st = SANE_STATUS_GOOD;
+ while (st != SANE_STATUS_EOF && py < im->ysize)
+ {
+ while (len > 0)
+ {
+ int bit, mask, val;
+ val = buffer[bufpos++]; len--;
+ mask = 0x80;
+ for (bit = 0; bit < 8 && px < pxmax; bit++)
+ {
+ ((UINT8**)(im->image32))[py][px]
+ = val&mask ? 0xFF : 0;
+ ((UINT8**)(im->image32))[py][pxa] = 0;
+ px += 4;
+ pxa += 4;
+ mask = mask >> 1;
+ }
+
+ if (px >= pxmax)
+ {
+ px = offset;
+ pxa = 3;
+ py++;
+ bufpos += padbytes;
+ len -= padbytes;
+ }
+ }
+ while (len <= 0 && st == SANE_STATUS_GOOD && remain > 0)
+ {
+ bufpos -= lastlen;
+ st = sane_read(self->h, buffer,
+ remain<(READSIZE) ? remain : (READSIZE), &len);
+ if (st && (st!=SANE_STATUS_EOF))
+ {
+ sane_cancel(self->h);
+ Py_BLOCK_THREADS
+ return PySane_Error(st);
+ }
+ remain -= len;
+ lastlen = len;
+ len -= bufpos;
+ }
+ }
+ break;
+ case 8:
+ case 16:
+ if (p.depth == 8)
+ {
+ padbytes = p.bytes_per_line - im->xsize;
+ incr = 1;
+ }
+ else
+ {
+ padbytes = p.bytes_per_line - 2 * im->xsize;
+ incr = 2;
+ bufpos = endian.c[0];
+ }
+ st = SANE_STATUS_GOOD;
+ while (st != SANE_STATUS_EOF && py < im->ysize)
+ {
+ while (len <= 0)
+ {
+ bufpos -= lastlen;
+ if (remain == 0)
+ {
+ sane_cancel(self->h);
+ Py_BLOCK_THREADS
+ PyErr_SetString(ErrorObject, "internal _sane error: premature end of scan");
+ return NULL;
+ }
+ st = sane_read(self->h, buffer,
+ remain<(READSIZE) ? remain : (READSIZE), &len);
+ if (st && (st!=SANE_STATUS_EOF))
+ {
+ sane_cancel(self->h);
+ Py_BLOCK_THREADS
+ return PySane_Error(st);
+ }
+ if (st == SANE_STATUS_EOF)
+ break;
+ lastlen = len;
+ remain -= len;
+ if (bufpos >= len)
+ len = 0;
+ else
+ len -= bufpos;
+ }
+ if (st == SANE_STATUS_EOF)
+ break;
+ ((UINT8**)(im->image32))[py][px] = buffer[bufpos];
+ ((UINT8**)(im->image32))[py][pxa] = 0;
+ bufpos += incr;
+ len -= incr;
+ px += 4;
+ pxa += 4;
+
+ if (px >= pxmax)
+ {
+ px = offset;
+ pxa = 3;
+ py++;
+ bufpos += padbytes;
+ len -= padbytes;
+ }
+ }
+ break;
+ default:
+ sane_cancel(self->h);
+ Py_BLOCK_THREADS
+ snprintf(errmsg, 80, "unsupported pixel depth: %i", p.depth);
+ PyErr_SetString(ErrorObject, errmsg);
+ return NULL;
+ }
+ if (!p.last_frame)
+ {
+ /* all sane_read calls in the above loop may return
+ SANE_STATUS_GOOD, but the backend may need another sane_read
+ call which returns SANE_STATUS_EOF in order to start
+ a new frame.
+ */
+ do {
+ st = sane_read(self->h, buffer, READSIZE, &len);
+ }
+ while (st == SANE_STATUS_GOOD);
+ if (st != SANE_STATUS_EOF)
+ {
+ Py_BLOCK_THREADS
+ sane_cancel(self->h);
+ return PySane_Error(st);
+ }
+
+ st = sane_start(self->h);
+ if (st)
+ {
+ Py_BLOCK_THREADS
+ return PySane_Error(st);
+ }
+ }
+ }
+ }
+ /* enforce SANE_STATUS_EOF. Can be necessary for ADF scans for some backends */
+ do {
+ st = sane_read(self->h, buffer, READSIZE, &len);
+ }
+ while (st == SANE_STATUS_GOOD);
+ if (st != SANE_STATUS_EOF)
+ {
+ sane_cancel(self->h);
+ Py_BLOCK_THREADS
+ return PySane_Error(st);
+ }
+
+ if (!noCancel)
+ sane_cancel(self->h);
+ Py_BLOCK_THREADS
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+#ifdef WITH_NUMARRAY
+
+#include "numarray/libnumarray.h"
+
+/* this global variable is set to 1 in 'init_sane()' after successfully
+ importing the numarray module. */
+int NUMARRAY_IMPORTED = 0;
+
+static PyObject *
+SaneDev_arr_snap(SaneDevObject *self, PyObject *args)
+{
+ SANE_Status st;
+ SANE_Byte buffer[READSIZE];
+ SANE_Int len;
+ SANE_Parameters p;
+
+ PyArrayObject *pyArr = NULL;
+ NumarrayType arrType;
+ int line, line_index, buffer_index, remain_bytes_line, num_pad_bytes;
+ int cp_num_bytes, total_remain, bpp, arr_bytes_per_line;
+ int pixels_per_line = -1;
+ char errmsg[80];
+
+ if (!NUMARRAY_IMPORTED)
+ {
+ PyErr_SetString(ErrorObject, "numarray package not available");
+ return NULL;
+ }
+
+ if (!PyArg_ParseTuple(args, "|i", &pixels_per_line))
+ return NULL;
+ if (self->h==NULL)
+ {
+ PyErr_SetString(ErrorObject, "SaneDev object is closed");
+ return NULL;
+ }
+
+ sane_get_parameters(self->h, &p);
+ if (p.format != SANE_FRAME_GRAY)
+ {
+ sane_cancel(self->h);
+ snprintf(errmsg, 80, "numarray only supports gray-scale images");
+ PyErr_SetString(ErrorObject, errmsg);
+ return NULL;
+ }
+
+ if (p.depth == 8)
+ {
+ bpp=1; /* bytes-per-pixel */
+ arrType = tUInt8;
+ }
+ else if (p.depth == 16)
+ {
+ bpp=2; /* bytes-per-pixel */
+ arrType = tUInt16;
+ }
+ else
+ {
+ sane_cancel(self->h);
+ snprintf(errmsg, 80, "arrsnap: unsupported pixel depth: %i", p.depth);
+ PyErr_SetString(ErrorObject, errmsg);
+ return NULL;
+ }
+
+ if (pixels_per_line < 1)
+ /* The user can choose a smaller result array than the actual scan */
+ pixels_per_line = p.pixels_per_line;
+ else
+ if (pixels_per_line > p.pixels_per_line)
+ {
+ PyErr_SetString(ErrorObject,"given pixels_per_line too big");
+ return NULL;
+ }
+ /* important: NumArray have indices like (y, x) !! */
+ if (!(pyArr = NA_NewArray(NULL, arrType, 2, p.lines, pixels_per_line)))
+ {
+ PyErr_SetString(ErrorObject, "failed to create NumArray object");
+ return NULL;
+ }
+
+ arr_bytes_per_line = pixels_per_line * bpp;
+ st=SANE_STATUS_GOOD;
+#ifdef WRITE_PGM
+ FILE *fp;
+ fp = fopen("sane_p5.pgm", "w");
+ fprintf(fp, "P5\n%d %d\n%d\n", p.pixels_per_line,
+ p.lines, (int) pow(2.0, (double) p.depth)-1);
+#endif
+ line_index = line = 0;
+ remain_bytes_line = arr_bytes_per_line;
+ total_remain = p.bytes_per_line * p.lines;
+ num_pad_bytes = p.bytes_per_line - arr_bytes_per_line;
+
+ while (st!=SANE_STATUS_EOF)
+ {
+ Py_BEGIN_ALLOW_THREADS
+ st = sane_read(self->h, buffer,
+ READSIZE < total_remain ? READSIZE : total_remain, &len);
+ Py_END_ALLOW_THREADS
+#ifdef WRITE_PGM
+ printf("p5_write: read %d of %d\n", len, READSIZE);
+ fwrite(buffer, 1, len, fp);
+#endif
+
+ buffer_index = 0;
+ total_remain -= len;
+
+ while (len > 0)
+ {
+ /* copy at most the number of bytes that fit into (the rest of)
+ one line: */
+ cp_num_bytes = (len > remain_bytes_line ? remain_bytes_line : len);
+ remain_bytes_line -= cp_num_bytes;
+ len -= cp_num_bytes;
+#ifdef DEBUG
+ printf("copying %d bytes from b_idx %d to d_idx %d\n",
+ cp_num_bytes, buffer_index,
+ line * arr_bytes_per_line + line_index);
+ printf("len is now %d\n", len);
+#endif
+ memcpy(pyArr->data + line * arr_bytes_per_line + line_index,
+ buffer + buffer_index, cp_num_bytes);
+
+ buffer_index += cp_num_bytes;
+ if (remain_bytes_line ==0)
+ {
+ /* The line has been completed, so reinitialize remain_bytes_line
+ increase the line counter, and reset line_index */
+#ifdef DEBUG
+ printf("line %d full, skipping %d bytes\n",line,num_pad_bytes);
+#endif
+ remain_bytes_line = arr_bytes_per_line;
+ line++;
+ line_index = 0;
+ /* Skip the number of bytes in the input stream which
+ are not used: */
+ len -= num_pad_bytes;
+ buffer_index += num_pad_bytes;
+ }
+ else
+ line_index += cp_num_bytes;
+ }
+ }
+#ifdef WRITE_PGM
+ fclose(fp);
+ printf("p5_write finished\n");
+#endif
+ sane_cancel(self->h);
+ return (PyObject*) pyArr;
+}
+
+
+
+#endif /* WITH_NUMARRAY */
+
+static PyMethodDef SaneDev_methods[] = {
+ {"get_parameters", (PyCFunction)SaneDev_get_parameters, 1},
+
+ {"get_options", (PyCFunction)SaneDev_get_options, 1},
+ {"get_option", (PyCFunction)SaneDev_get_option, 1},
+ {"set_option", (PyCFunction)SaneDev_set_option, 1},
+ {"set_auto_option", (PyCFunction)SaneDev_set_auto_option, 1},
+
+ {"start", (PyCFunction)SaneDev_start, 1},
+ {"cancel", (PyCFunction)SaneDev_cancel, 1},
+ {"snap", (PyCFunction)SaneDev_snap, 1},
+#ifdef WITH_NUMARRAY
+ {"arr_snap", (PyCFunction)SaneDev_arr_snap, 1},
+#endif /* WITH_NUMARRAY */
+ {"fileno", (PyCFunction)SaneDev_fileno, 1},
+ {"close", (PyCFunction)SaneDev_close, 1},
+ {NULL, NULL} /* sentinel */
+};
+
+static PyObject *
+SaneDev_getattr(SaneDevObject *self, char *name)
+{
+ return Py_FindMethod(SaneDev_methods, (PyObject *)self, name);
+}
+
+staticforward PyTypeObject SaneDev_Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /*ob_size*/
+ "SaneDev", /*tp_name*/
+ sizeof(SaneDevObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor)SaneDev_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ (getattrfunc)SaneDev_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+};
+
+/* --------------------------------------------------------------------- */
+
+static PyObject *
+PySane_init(PyObject *self, PyObject *args)
+{
+ SANE_Status st;
+ SANE_Int version;
+
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ /* XXX Authorization is not yet supported */
+ st=sane_init(&version, NULL);
+ if (st) return PySane_Error(st);
+ return Py_BuildValue("iiii", version, SANE_VERSION_MAJOR(version),
+ SANE_VERSION_MINOR(version), SANE_VERSION_BUILD(version));
+}
+
+static PyObject *
+PySane_exit(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ sane_exit();
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+PySane_get_devices(PyObject *self, PyObject *args)
+{
+ SANE_Device **devlist;
+ SANE_Device *dev;
+ SANE_Status st;
+ PyObject *list;
+ int local_only, i;
+
+ if (!PyArg_ParseTuple(args, "|i", &local_only))
+ {
+ return NULL;
+ }
+
+ st=sane_get_devices(&devlist, local_only);
+ if (st) return PySane_Error(st);
+ if (!(list = PyList_New(0)))
+ return NULL;
+ for(i=0; devlist[i]!=NULL; i++)
+ {
+ dev=devlist[i];
+ PyList_Append(list, Py_BuildValue("ssss", dev->name, dev->vendor,
+ dev->model, dev->type));
+ }
+
+ return list;
+}
+
+/* Function returning new SaneDev object */
+
+static PyObject *
+PySane_open(PyObject *self, PyObject *args)
+{
+ SaneDevObject *rv;
+ SANE_Status st;
+ char *name;
+
+ if (!PyArg_ParseTuple(args, "s", &name))
+ return NULL;
+ rv = newSaneDevObject();
+ if ( rv == NULL )
+ return NULL;
+ st = sane_open(name, &(rv->h));
+ if (st)
+ {
+ Py_DECREF(rv);
+ return PySane_Error(st);
+ }
+ return (PyObject *)rv;
+}
+
+static PyObject *
+PySane_OPTION_IS_ACTIVE(PyObject *self, PyObject *args)
+{
+ SANE_Int cap;
+ long lg;
+
+ if (!PyArg_ParseTuple(args, "l", &lg))
+ return NULL;
+ cap=lg;
+ return PyInt_FromLong( SANE_OPTION_IS_ACTIVE(cap));
+}
+
+static PyObject *
+PySane_OPTION_IS_SETTABLE(PyObject *self, PyObject *args)
+{
+ SANE_Int cap;
+ long lg;
+
+ if (!PyArg_ParseTuple(args, "l", &lg))
+ return NULL;
+ cap=lg;
+ return PyInt_FromLong( SANE_OPTION_IS_SETTABLE(cap));
+}
+
+
+/* List of functions defined in the module */
+
+static PyMethodDef PySane_methods[] = {
+ {"init", PySane_init, 1},
+ {"exit", PySane_exit, 1},
+ {"get_devices", PySane_get_devices, 1},
+ {"_open", PySane_open, 1},
+ {"OPTION_IS_ACTIVE", PySane_OPTION_IS_ACTIVE, 1},
+ {"OPTION_IS_SETTABLE", PySane_OPTION_IS_SETTABLE, 1},
+ {NULL, NULL} /* sentinel */
+};
+
+
+static void
+insint(PyObject *d, char *name, int value)
+{
+ PyObject *v = PyInt_FromLong((long) value);
+ if (!v || PyDict_SetItemString(d, name, v))
+ Py_FatalError("can't initialize sane module");
+
+ Py_DECREF(v);
+}
+
+void
+init_sane(void)
+{
+ PyObject *m, *d;
+
+ /* Create the module and add the functions */
+ m = Py_InitModule("_sane", PySane_methods);
+
+ /* Add some symbolic constants to the module */
+ d = PyModule_GetDict(m);
+ ErrorObject = PyString_FromString("_sane.error");
+ PyDict_SetItemString(d, "error", ErrorObject);
+
+ insint(d, "INFO_INEXACT", SANE_INFO_INEXACT);
+ insint(d, "INFO_RELOAD_OPTIONS", SANE_INFO_RELOAD_OPTIONS);
+ insint(d, "RELOAD_PARAMS", SANE_INFO_RELOAD_PARAMS);
+
+ insint(d, "FRAME_GRAY", SANE_FRAME_GRAY);
+ insint(d, "FRAME_RGB", SANE_FRAME_RGB);
+ insint(d, "FRAME_RED", SANE_FRAME_RED);
+ insint(d, "FRAME_GREEN", SANE_FRAME_GREEN);
+ insint(d, "FRAME_BLUE", SANE_FRAME_BLUE);
+
+ insint(d, "CONSTRAINT_NONE", SANE_CONSTRAINT_NONE);
+ insint(d, "CONSTRAINT_RANGE", SANE_CONSTRAINT_RANGE);
+ insint(d, "CONSTRAINT_WORD_LIST", SANE_CONSTRAINT_WORD_LIST);
+ insint(d, "CONSTRAINT_STRING_LIST", SANE_CONSTRAINT_STRING_LIST);
+
+ insint(d, "TYPE_BOOL", SANE_TYPE_BOOL);
+ insint(d, "TYPE_INT", SANE_TYPE_INT);
+ insint(d, "TYPE_FIXED", SANE_TYPE_FIXED);
+ insint(d, "TYPE_STRING", SANE_TYPE_STRING);
+ insint(d, "TYPE_BUTTON", SANE_TYPE_BUTTON);
+ insint(d, "TYPE_GROUP", SANE_TYPE_GROUP);
+
+ insint(d, "UNIT_NONE", SANE_UNIT_NONE);
+ insint(d, "UNIT_PIXEL", SANE_UNIT_PIXEL);
+ insint(d, "UNIT_BIT", SANE_UNIT_BIT);
+ insint(d, "UNIT_MM", SANE_UNIT_MM);
+ insint(d, "UNIT_DPI", SANE_UNIT_DPI);
+ insint(d, "UNIT_PERCENT", SANE_UNIT_PERCENT);
+ insint(d, "UNIT_MICROSECOND", SANE_UNIT_MICROSECOND);
+
+ insint(d, "CAP_SOFT_SELECT", SANE_CAP_SOFT_SELECT);
+ insint(d, "CAP_HARD_SELECT", SANE_CAP_HARD_SELECT);
+ insint(d, "CAP_SOFT_DETECT", SANE_CAP_SOFT_DETECT);
+ insint(d, "CAP_EMULATED", SANE_CAP_EMULATED);
+ insint(d, "CAP_AUTOMATIC", SANE_CAP_AUTOMATIC);
+ insint(d, "CAP_INACTIVE", SANE_CAP_INACTIVE);
+ insint(d, "CAP_ADVANCED", SANE_CAP_ADVANCED);
+
+ /* handy for checking array lengths: */
+ insint(d, "SANE_WORD_SIZE", sizeof(SANE_Word));
+
+ /* possible return values of set_option() */
+ insint(d, "INFO_INEXACT", SANE_INFO_INEXACT);
+ insint(d, "INFO_RELOAD_OPTIONS", SANE_INFO_RELOAD_OPTIONS);
+ insint(d, "INFO_RELOAD_PARAMS", SANE_INFO_RELOAD_PARAMS);
+
+ /* Check for errors */
+ if (PyErr_Occurred())
+ Py_FatalError("can't initialize module _sane");
+
+#ifdef WITH_NUMARRAY
+ import_libnumarray();
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ else
+ /* this global variable is declared just in front of the
+ arr_snap() function and should be set to 1 after
+ successfully importing the numarray module. */
+ NUMARRAY_IMPORTED = 1;
+
+#endif /* WITH_NUMARRAY */
+}
diff --git a/Imaging/Sane/demo_numarray.py b/Imaging/Sane/demo_numarray.py
new file mode 100644
index 0000000..0104af2
--- /dev/null
+++ b/Imaging/Sane/demo_numarray.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+
+#
+# Shows how to scan a 16 bit grayscale image into a numarray object
+#
+
+# Get the path set up to find PIL modules if not installed yet:
+import sys ; sys.path.append('../PIL')
+
+from numarray import *
+import sane
+import Image
+
+def toImage(arr):
+ if arr.type().bytes == 1:
+ # need to swap coordinates btw array and image (with [::-1])
+ im = Image.fromstring('L', arr.shape[::-1], arr.tostring())
+ else:
+ arr_c = arr - arr.min()
+ arr_c *= (255./arr_c.max())
+ arr = arr_c.astype(UInt8)
+ # need to swap coordinates btw array and image (with [::-1])
+ im = Image.fromstring('L', arr.shape[::-1], arr.tostring())
+ return im
+
+print 'SANE version:', sane.init()
+print 'Available devices=', sane.get_devices()
+
+s = sane.open(sane.get_devices()[0][0])
+
+# Set scan parameters
+s.mode = 'gray'
+s.br_x=320. ; s.br_y=240.
+
+print 'Device parameters:', s.get_parameters()
+
+s.depth=16
+arr16 = s.arr_scan()
+toImage(arr16).show()
diff --git a/Imaging/Sane/demo_pil.py b/Imaging/Sane/demo_pil.py
new file mode 100644
index 0000000..016361f
--- /dev/null
+++ b/Imaging/Sane/demo_pil.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+
+#
+# Shows how to scan a color image into a PIL rgb-image
+#
+
+# Get the path set up to find PIL modules if not installed yet:
+import sys ; sys.path.append('../PIL')
+
+import sane
+print 'SANE version:', sane.init()
+print 'Available devices=', sane.get_devices()
+
+s = sane.open(sane.get_devices()[0][0])
+
+s.mode = 'color'
+s.br_x=320. ; s.br_y=240.
+
+print 'Device parameters:', s.get_parameters()
+
+# Initiate the scan
+s.start()
+
+# Get an Image object
+# (For my B&W QuickCam, this is a grey-scale image. Other scanning devices
+# may return a
+im=s.snap()
+
+# Write the image out as a GIF file
+#im.save('foo.gif')
+
+# The show method() simply saves the image to a temporary file and calls "xv".
+im.show()
diff --git a/Imaging/Sane/sane.py b/Imaging/Sane/sane.py
new file mode 100644
index 0000000..27be5a2
--- /dev/null
+++ b/Imaging/Sane/sane.py
@@ -0,0 +1,289 @@
+# sane.py
+#
+# Python wrapper on top of the _sane module, which is in turn a very
+# thin wrapper on top of the SANE library. For a complete understanding
+# of SANE, consult the documentation at the SANE home page:
+# http://www.mostang.com/sane/ .
+
+__version__ = '2.0'
+__author__ = ['Andrew Kuchling', 'Ralph Heinkel']
+
+from PIL import Image
+
+import _sane
+from _sane import *
+
+TYPE_STR = { TYPE_BOOL: "TYPE_BOOL", TYPE_INT: "TYPE_INT",
+ TYPE_FIXED: "TYPE_FIXED", TYPE_STRING: "TYPE_STRING",
+ TYPE_BUTTON: "TYPE_BUTTON", TYPE_GROUP: "TYPE_GROUP" }
+
+UNIT_STR = { UNIT_NONE: "UNIT_NONE",
+ UNIT_PIXEL: "UNIT_PIXEL",
+ UNIT_BIT: "UNIT_BIT",
+ UNIT_MM: "UNIT_MM",
+ UNIT_DPI: "UNIT_DPI",
+ UNIT_PERCENT: "UNIT_PERCENT",
+ UNIT_MICROSECOND: "UNIT_MICROSECOND" }
+
+
+class Option:
+ """Class representing a SANE option.
+ Attributes:
+ index -- number from 0 to n, giving the option number
+ name -- a string uniquely identifying the option
+ title -- single-line string containing a title for the option
+ desc -- a long string describing the option; useful as a help message
+ type -- type of this option. Possible values: TYPE_BOOL,
+ TYPE_INT, TYPE_STRING, and so forth.
+ unit -- units of this option. Possible values: UNIT_NONE,
+ UNIT_PIXEL, etc.
+ size -- size of the value in bytes
+ cap -- capabilities available; CAP_EMULATED, CAP_SOFT_SELECT, etc.
+ constraint -- constraint on values. Possible values:
+ None : No constraint
+ (min,max,step) Integer values, from min to max, stepping by
+ list of integers or strings: only the listed values are allowed
+ """
+
+ def __init__(self, args, scanDev):
+ import string
+ self.scanDev = scanDev # needed to get current value of this option
+ self.index, self.name = args[0], args[1]
+ self.title, self.desc = args[2], args[3]
+ self.type, self.unit = args[4], args[5]
+ self.size, self.cap = args[6], args[7]
+ self.constraint = args[8]
+ def f(x):
+ if x=='-': return '_'
+ else: return x
+ if type(self.name)!=type(''): self.py_name=str(self.name)
+ else: self.py_name=string.join(map(f, self.name), '')
+
+ def is_active(self):
+ return _sane.OPTION_IS_ACTIVE(self.cap)
+ def is_settable(self):
+ return _sane.OPTION_IS_SETTABLE(self.cap)
+ def __repr__(self):
+ if self.is_settable():
+ settable = 'yes'
+ else:
+ settable = 'no'
+ if self.is_active():
+ active = 'yes'
+ curValue = repr(getattr(self.scanDev, self.py_name))
+ else:
+ active = 'no'
+ curValue = '<not available, inactive option>'
+ s = """\nName: %s
+Cur value: %s
+Index: %d
+Title: %s
+Desc: %s
+Type: %s
+Unit: %s
+Constr: %s
+active: %s
+settable: %s\n""" % (self.py_name, curValue,
+ self.index, self.title, self.desc,
+ TYPE_STR[self.type], UNIT_STR[self.unit],
+ `self.constraint`, active, settable)
+ return s
+
+
+class _SaneIterator:
+ """ intended for ADF scans.
+ """
+
+ def __init__(self, device):
+ self.device = device
+
+ def __iter__(self):
+ return self
+
+ def __del__(self):
+ self.device.cancel()
+
+ def next(self):
+ try:
+ self.device.start()
+ except error, v:
+ if v == 'Document feeder out of documents':
+ raise StopIteration
+ else:
+ raise
+ return self.device.snap(1)
+
+
+
+class SaneDev:
+ """Class representing a SANE device.
+ Methods:
+ start() -- initiate a scan, using the current settings
+ snap() -- snap a picture, returning an Image object
+ arr_snap() -- snap a picture, returning a numarray object
+ cancel() -- cancel an in-progress scanning operation
+ fileno() -- return the file descriptor for the scanner (handy for select)
+
+ Also available, but rather low-level:
+ get_parameters() -- get the current parameter settings of the device
+ get_options() -- return a list of tuples describing all the options.
+
+ Attributes:
+ optlist -- list of option names
+
+ You can also access an option name to retrieve its value, and to
+ set it. For example, if one option has a .name attribute of
+ imagemode, and scanner is a SaneDev object, you can do:
+ print scanner.imagemode
+ scanner.imagemode = 'Full frame'
+ scanner.['imagemode'] returns the corresponding Option object.
+ """
+ def __init__(self, devname):
+ d=self.__dict__
+ d['sane_signature'] = self._getSaneSignature(devname)
+ d['scanner_model'] = d['sane_signature'][1:3]
+ d['dev'] = _sane._open(devname)
+ self.__load_option_dict()
+
+ def _getSaneSignature(self, devname):
+ devices = get_devices()
+ if not devices:
+ raise RuntimeError('no scanner available')
+ for dev in devices:
+ if devname == dev[0]:
+ return dev
+ raise RuntimeError('no such scan device "%s"' % devname)
+
+ def __load_option_dict(self):
+ d=self.__dict__
+ d['opt']={}
+ optlist=d['dev'].get_options()
+ for t in optlist:
+ o=Option(t, self)
+ if o.type!=TYPE_GROUP:
+ d['opt'][o.py_name]=o
+
+ def __setattr__(self, key, value):
+ dev=self.__dict__['dev']
+ optdict=self.__dict__['opt']
+ if not optdict.has_key(key):
+ self.__dict__[key]=value ; return
+ opt=optdict[key]
+ if opt.type==TYPE_GROUP:
+ raise AttributeError, "Groups can't be set: "+key
+ if not _sane.OPTION_IS_ACTIVE(opt.cap):
+ raise AttributeError, 'Inactive option: '+key
+ if not _sane.OPTION_IS_SETTABLE(opt.cap):
+ raise AttributeError, "Option can't be set by software: "+key
+ if type(value) == int and opt.type == TYPE_FIXED:
+ # avoid annoying errors of backend if int is given instead float:
+ value = float(value)
+ self.last_opt = dev.set_option(opt.index, value)
+ # do binary AND to find if we have to reload options:
+ if self.last_opt & INFO_RELOAD_OPTIONS:
+ self.__load_option_dict()
+
+ def __getattr__(self, key):
+ dev=self.__dict__['dev']
+ optdict=self.__dict__['opt']
+ if key=='optlist':
+ return self.opt.keys()
+ if key=='area':
+ return (self.tl_x, self.tl_y),(self.br_x, self.br_y)
+ if not optdict.has_key(key):
+ raise AttributeError, 'No such attribute: '+key
+ opt=optdict[key]
+ if opt.type==TYPE_BUTTON:
+ raise AttributeError, "Buttons don't have values: "+key
+ if opt.type==TYPE_GROUP:
+ raise AttributeError, "Groups don't have values: "+key
+ if not _sane.OPTION_IS_ACTIVE(opt.cap):
+ raise AttributeError, 'Inactive option: '+key
+ value = dev.get_option(opt.index)
+ return value
+
+ def __getitem__(self, key):
+ return self.opt[key]
+
+ def get_parameters(self):
+ """Return a 5-tuple holding all the current device settings:
+ (format, last_frame, (pixels_per_line, lines), depth, bytes_per_line)
+
+- format is one of 'L' (grey), 'RGB', 'R' (red), 'G' (green), 'B' (blue).
+- last_frame [bool] indicates if this is the last frame of a multi frame image
+- (pixels_per_line, lines) specifies the size of the scanned image (x,y)
+- lines denotes the number of scanlines per frame
+- depth gives number of pixels per sample
+"""
+ return self.dev.get_parameters()
+
+ def get_options(self):
+ "Return a list of tuples describing all the available options"
+ return self.dev.get_options()
+
+ def start(self):
+ "Initiate a scanning operation"
+ return self.dev.start()
+
+ def cancel(self):
+ "Cancel an in-progress scanning operation"
+ return self.dev.cancel()
+
+ def snap(self, no_cancel=0):
+ "Snap a picture, returning a PIL image object with the results"
+ (mode, last_frame,
+ (xsize, ysize), depth, bytes_per_line) = self.get_parameters()
+ if mode in ['gray', 'red', 'green', 'blue']:
+ format = 'L'
+ elif mode == 'color':
+ format = 'RGB'
+ else:
+ raise ValueError('got unknown "mode" from self.get_parameters()')
+ im=Image.new(format, (xsize,ysize))
+ self.dev.snap( im.im.id, no_cancel )
+ return im
+
+ def scan(self):
+ self.start()
+ return self.snap()
+
+ def multi_scan(self):
+ return _SaneIterator(self)
+
+ def arr_snap(self, multipleOf=1):
+ """Snap a picture, returning a numarray object with the results.
+ By default the resulting array has the same number of pixels per
+ line as specified in self.get_parameters()[2][0]
+ However sometimes it is necessary to obtain arrays where
+ the number of pixels per line is e.g. a multiple of 4. This can then
+ be achieved with the option 'multipleOf=4'. So if the scanner
+ scanned 34 pixels per line, you will obtain an array with 32 pixels
+ per line.
+ """
+ (mode, last_frame, (xsize, ysize), depth, bpl) = self.get_parameters()
+ if not mode in ['gray', 'red', 'green', 'blue']:
+ raise RuntimeError('arr_snap() only works with monochrome images')
+ if multipleOf < 1:
+ raise ValueError('option "multipleOf" must be a positive number')
+ elif multipleOf > 1:
+ pixels_per_line = xsize - divmod(xsize, 4)[1]
+ else:
+ pixels_per_line = xsize
+ return self.dev.arr_snap(pixels_per_line)
+
+ def arr_scan(self, multipleOf=1):
+ self.start()
+ return self.arr_snap(multipleOf=multipleOf)
+
+ def fileno(self):
+ "Return the file descriptor for the scanning device"
+ return self.dev.fileno()
+
+ def close(self):
+ self.dev.close()
+
+
+def open(devname):
+ "Open a device for scanning"
+ new=SaneDev(devname)
+ return new
diff --git a/Imaging/Sane/sanedoc.txt b/Imaging/Sane/sanedoc.txt
new file mode 100644
index 0000000..db86938
--- /dev/null
+++ b/Imaging/Sane/sanedoc.txt
@@ -0,0 +1,294 @@
+The _sane_ module is an Python interface to the SANE (Scanning is Now
+Easy) library, which provides access to various raster scanning
+devices such as flatbed scanners and digital cameras. For more
+information about SANE, consult the SANE Web site at
+http://www.mostang.com/sane/ . Note that this
+documentation doesn't duplicate all the information in the SANE
+documentation, which you must also consult to get a complete
+understanding.
+
+This module has been originally developed by A.M. Kuchling (amk1@erols.com),
+now development has been taken over by Ralph Heinkel (rheinkel-at-email.de).
+If you write to me please make sure to have the word 'SANE' or 'sane' in
+the subject of your mail, otherwise it might be classified as spam in the
+future.
+
+
+The module exports two object types, a bunch of constants, and two
+functions.
+
+get_devices()
+ Return a list of 4-tuples containing the available scanning
+ devices. Each tuple contains 4 strings: the device name, suitable for
+ passing to _open()_; the device's vendor; the model; and the type of
+ device, such as 'virtual device' or 'video camera'.
+
+ >>> import sane ; sane.get_devices()
+ [('epson:libusb:001:004', 'Epson', 'GT-8300', 'flatbed scanner')]
+
+open(devicename)
+ Open a device, given a string containing its name. SANE
+ devices have names like 'epson:libusb:001:004'. If the attempt
+ to open the device fails, a _sane.error_ exception will be raised. If
+ there are no problems, a SaneDev object will be returned.
+ As an easy way to open the scanner (if only one is available) just type
+ >>> sane.open(sane.get_devices()[0][0])
+
+
+SaneDev objects
+===============
+
+The basic process of scanning an image consists of getting a SaneDev
+object for the device, setting various parameters, starting the scan,
+and then reading the image data. Images are composed of one or more
+frames; greyscale and one-pass colour scanners return a single frame
+containing all the image data, but 3-pass scanners will usually return
+3 frames, one for each of the red, green, blue channels.
+
+Methods:
+--------
+fileno()
+ Returns a file descriptor for the scanning device. This
+ method's existence means that SaneDev objects can be used by the
+ select module.
+
+get_parameters()
+ Return a tuple containing information about the current settings of
+ the device and the current frame: (format, last_frame,
+ pixels_per_line, lines, depth, bytes_per_line).
+
+ mode -- 'gray' for greyscale image, 'color' for RGB image, or
+ one of 'red', 'green', 'blue' if the image is a single
+ channel of an RGB image (from PIL's point of view,
+ this is equivalent to 'L').
+ last_frame -- A Boolean value, which is true if this is the
+ last frame of the image, and false otherwise.
+ pixels_per_line -- Width of the frame.
+ lines -- Height of the frame.
+ depth -- Depth of the image, measured in bits. SANE will only
+ allow using 8, 16, or 24-bit depths.
+ bytes_per_line -- Bytes required to store a single line of
+ data, as computed from pixels_per_line and depth.
+
+start()
+ Start a scan. This function must be called before the
+ _snap()_ method can be used.
+
+cancel()
+ Cancel a scan already in progress.
+
+snap(no_cancel=0)
+ Snap a single frame of data, returning a PIL Image object
+ containing the data. If no_cancel is false, the Sane library function
+ sane_cancel is called after the scan. This is reasonable in most cases,
+ but may cause backends for duplex ADF scanners to drop the backside image,
+ when snap() is called for the front side image. If no_cancel is true,
+ cancel() should be called manually, after all scans are finished.
+
+scan()
+ This is just a shortcut for s.start(); s.snap()
+ Returns a PIL image
+
+multi_scan()
+ This method returns an iterator. It is intended to be used for
+ scanning with an automatic document feeder. The next() method of the
+ iterator tries to start a scan. If this is successful, it returns a
+ PIL Image object, like scan(); if the document feeder runs out of
+ paper, it raises StopIteration, thereby signaling that the sequence
+ is ran out of items.
+
+arr_snap(multipleOf=1)
+ same as snap, but the result is a NumArray object. (Not that
+ num_array must be installed already at compilation time, otherwise
+ this feature will not be activated).
+ By default the resulting array has the same number of pixels per
+ line as specified in self.get_parameters()[2][0]
+ However sometimes it is necessary to obtain arrays where
+ the number of pixels per line is e.g. a multiple of 4. This can then
+ be achieved with the option 'multipleOf=4'. So if the scanner
+ scanned 34 pixels per line, you will obtain an array with 32 pixels
+ per line.
+ Note that this only works with monochrome images (e.g. gray-scales)
+
+arr_scan(multipleOf=1)
+ This is just a shortcut for s.start(); s.arr_snap(multipleOf=1)
+ Returns a NumArray object
+
+close()
+ Closes the object.
+
+
+Attributes:
+-----------
+SaneDev objects have a few fixed attributes which are always
+available, and a larger collection of attributes which vary depending
+on the device. An Epson 1660 photo scanner has attributes like
+'mode', 'depth', etc.
+Another (pseudo scanner), the _pnm:0_ device, takes a PNM file and
+simulates a scanner using the image data; a SaneDev object
+representing the _pnm:0_ device therefore has a _filename_ attribute
+which can be changed to specify the filename, _contrast_ and
+_brightness_ attributes to modify the returned image, and so forth.
+
+The values of the scanner options may be an integer, floating-point
+value, or string, depending on the nature of the option.
+
+sane_signature
+ The tuple for this scandev that is returned by sane.get_devices()
+ e.g. ('epson:libusb:001:006', 'Epson', 'GT-8300', 'flatbed scanner')
+
+scanner_model
+ same as sane_signature[1:3], i.e. ('Epson', 'GT-8300') for the case above.
+
+optlist
+ A list containing the all the options supported by this device.
+
+ >>> import sane ; s=sane.open('epson:libusb:001:004') ; s.optlist
+ ['focus_position', 'color_correction', 'sharpness', ...., 'br_x']
+
+A closer look at all options listed in s.optlist can be obtained
+through the SaneOption objects.
+
+SaneOption objects
+==================
+
+SANE's option handling is its most elaborate subsystem, intended to
+allow automatically generating dialog boxes and prompts for user
+configuration of the scanning device. The SaneOption object can be
+used to get a human-readable name and description for an option, the
+units to use, and what the legal values are. No information about the
+current value of the option is available; for that, read the
+corresponding attribute of a SaneDev object.
+
+This documentation does not explain all the details of SANE's option
+handling; consult the SANE documentation for all the details.
+
+A scandevice option is accessed via __getitem__. For example
+s['mode'] returns the option descriptor for the mode-option which
+controls whether the scanner works in color, grayscale, or b/w mode.
+
+>>> s['mode']
+Name: mode
+Cur value: Color
+Index: 2
+Title: Scan mode
+Desc: Selects the scan mode (e.g., lineart, monochrome, or color).
+Type: TYPE_STRING
+Unit: UNIT_NONE
+Constr: ['Binary', 'Gray', 'Color']
+active: yes
+settable: yes
+
+In order to change 'mode' to 'gray', just type:
+>>> s.mode = 'gray'
+
+
+With the attributes and methods of sane-option objects it is possible
+to access individual option values:
+
+is_active()
+ Returns true if the option is active.
+
+is_settable()
+ Returns true if the option can be set under software control.
+
+
+Attributes:
+
+cap
+ An integer containing various flags about the object's
+ capabilities; whether it's active, whether it's settable, etc. Also
+ available as the _capability_ attribute.
+
+constraint
+ The constraint placed on the value of this option. If it's
+ _None_, there are essentially no constraint of the value. It may also
+ be a list of integers or strings, in which case the value *must* be
+ one of the possibilities in the list. Numeric values may have a
+ 3-tuple as the constraint; this 3-tuple contains _(minimum, maximum,
+ increment)_, and the value must be in the defined range.
+
+desc
+ A lengthy description of what the option does; it may be shown
+ to the user for clarification.
+
+index
+ An integer giving the option's index in the option list.
+
+name
+ A short name for the option, as it comes from the sane-backend.
+
+py_name
+ The option's name, as a legal Python identifier. The name
+ attribute may contain the '-' character, so it will be converted to
+ '_' for the py_name attribute.
+
+size
+ For a string-valued option, this is the maximum length allowed.
+
+title
+ A single-line string that can be used as a title string.
+
+type
+ A constant giving the type of this option: will be one of the following
+ constants found in the SANE module:
+ TYPE_BOOL
+ TYPE_INT
+ TYPE_FIXED
+ TYPE_STRING
+ TYPE_BUTTON
+ TYPE_GROUP
+
+unit
+ For numeric-valued options, this is a constant representing
+ the unit used for this option. It will be one of the following
+ constants found in the SANE module:
+ UNIT_NONE
+ UNIT_PIXEL
+ UNIT_BIT
+ UNIT_MM
+ UNIT_DPI
+ UNIT_PERCENT
+
+
+
+Example us usage:
+=================
+>>> import sane
+>>> print 'SANE version:', sane.init()
+>>> print 'Available devices=', sane.get_devices()
+SANE version: (16777230, 1, 0, 14)
+>>> s = sane.open(sane.get_devices()[0][0])
+>>> print 'Device parameters:', s.get_parameters()
+Device parameters: ('L', 1, (424, 585), 1, 53)
+>>> print s.resolution
+50
+
+## In order to scan a color image into a PIL object:
+>>> s.mode = 'color'
+>>> s.start()
+>>> img = s.snap()
+>>> img.show()
+
+
+## In order to obtain a 16-bit grayscale image at 100DPI in a numarray object
+## with bottom-right coordinates set to (160, 120) [in millimeter] :
+>>> s.mode = 'gray'
+>>> s.br_x=160. ; s.br_y=120.
+>>> s.resolution = 100
+>>> s.depth=16
+>>> s.start()
+>>> s.get_parameters()[2] # just check the size
+(624, 472)
+>>> arr16 = s.arr_snap()
+>>> arr16
+array([[63957, 64721, 65067, ..., 65535, 65535, 65535],
+ [63892, 64342, 64236, ..., 65535, 65535, 65535],
+ [64286, 64248, 64705, ..., 65535, 65535, 65535],
+ ...,
+ [65518, 65249, 65058, ..., 65535, 65535, 65535],
+ [64435, 65047, 65081, ..., 65535, 65535, 65535],
+ [65309, 65438, 65535, ..., 65535, 65535, 65535]], type=UInt16)
+>>> arr16.shape # inverse order of coordinates, first y, then x!
+(472, 624)
+
diff --git a/Imaging/Sane/setup.py b/Imaging/Sane/setup.py
new file mode 100644
index 0000000..3837198
--- /dev/null
+++ b/Imaging/Sane/setup.py
@@ -0,0 +1,24 @@
+from distutils.core import setup, Extension
+
+PIL_BUILD_DIR = '..'
+PIL_IMAGING_DIR = PIL_BUILD_DIR+'/libImaging'
+
+defs = []
+try:
+ import numarray
+ defs.append(('WITH_NUMARRAY',None))
+except ImportError:
+ pass
+
+sane = Extension('_sane',
+ include_dirs = [PIL_IMAGING_DIR],
+ libraries = ['sane'],
+ library_dirs = [PIL_IMAGING_DIR],
+ define_macros = defs,
+ sources = ['_sane.c'])
+
+setup (name = 'pysane',
+ version = '2.0',
+ description = 'This is the pysane package',
+ py_modules = ['sane'],
+ ext_modules = [sane])
diff --git a/Imaging/Scripts/README b/Imaging/Scripts/README
new file mode 100644
index 0000000..a09b062
--- /dev/null
+++ b/Imaging/Scripts/README
@@ -0,0 +1,83 @@
+-------
+Scripts
+-------
+
+This directory contains a number of more or less trivial utilities
+and demo programs.
+
+Comments and contributions are welcome.
+
+</F>
+
+--------------------------------------------------------------------
+pildriver.py (by Eric S. Raymond)
+
+A class implementing an image-processing calculator for scripts.
+Parses lists of commnds (or, called interactively, command-line
+arguments) into image loads, transformations, and saves.
+
+--------------------------------------------------------------------
+viewer.py
+
+A simple image viewer. Can display all file formats handled by
+PIL. Transparent images are properly handled.
+
+--------------------------------------------------------------------
+thresholder.py
+
+A simple utility that demonstrates how a transparent 1-bit overlay
+can be used to show the current thresholding of an 8-bit image.
+
+--------------------------------------------------------------------
+enhancer.py
+
+Illustrates the ImageEnhance module. Drag the sliders to modify the
+images. This might be very slow on some platforms, depending on the
+Tk version.
+
+--------------------------------------------------------------------
+painter.py
+
+Illustrates how a painting program could be based on PIL and Tk.
+Press the left mouse button and drag over the image to remove the
+colour. Some clever tricks have been used to get decent performance
+when updating the screen; see the sources for details.
+
+--------------------------------------------------------------------
+player.py
+
+A simple image sequence player. You can use either a sequence format
+like FLI/FLC, GIF, or ARG, or give a number of images which are
+interpreted as frames in a sequence. All frames must have the same
+size.
+
+--------------------------------------------------------------------
+gifmaker.py
+
+Convert a sequence file to a GIF animation.
+
+Note that the GIF encoder provided with this release of PIL writes
+uncompressed GIF files only, so the resulting animations are rather
+large compared with these created by other tools.
+
+--------------------------------------------------------------------
+explode.py
+
+Split a sequence file into individual frames.
+
+--------------------------------------------------------------------
+image2py.py
+
+Convert an image to a Python module containing an IMAGE variable.
+Note that the module using the module must include JPEG and ZIP
+decoders, unless the -u option is used.
+
+--------------------------------------------------------------------
+olesummary.py
+
+Uses the OleFileIO module to dump the summary information from an OLE
+structured storage file. This works with most OLE files, including
+Word documents, FlashPix images, etc.
+
+Note that datetime fields currently show the number of seconds since
+January 1st, 1601.
diff --git a/Imaging/Scripts/enhancer.py b/Imaging/Scripts/enhancer.py
new file mode 100644
index 0000000..d581658
--- /dev/null
+++ b/Imaging/Scripts/enhancer.py
@@ -0,0 +1,53 @@
+#
+# The Python Imaging Library
+# $Id: enhancer.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# this demo script creates four windows containing an image and a slider.
+# drag the slider to modify the image.
+#
+
+from Tkinter import *
+import Image, ImageTk, ImageEnhance
+import sys
+
+#
+# enhancer widget
+
+class Enhance(Frame):
+ def __init__(self, master, image, name, enhancer, lo, hi):
+ Frame.__init__(self, master)
+
+ # set up the image
+ self.tkim = ImageTk.PhotoImage(image.mode, image.size)
+ self.enhancer = enhancer(image)
+ self.update("1.0") # normalize
+
+ # image window
+ Label(self, image=self.tkim).pack()
+
+ # scale
+ s = Scale(self, label=name, orient=HORIZONTAL,
+ from_=lo, to=hi, resolution=0.01,
+ command=self.update)
+ s.set(self.value)
+ s.pack()
+
+ def update(self, value):
+ self.value = eval(value)
+ self.tkim.paste(self.enhancer.enhance(self.value))
+
+#
+# main
+
+root = Tk()
+
+im = Image.open(sys.argv[1])
+
+im.thumbnail((200, 200))
+
+Enhance(root, im, "Color", ImageEnhance.Color, 0.0, 4.0).pack()
+Enhance(Toplevel(), im, "Sharpness", ImageEnhance.Sharpness, -2.0, 2.0).pack()
+Enhance(Toplevel(), im, "Brightness", ImageEnhance.Brightness, -1.0, 3.0).pack()
+Enhance(Toplevel(), im, "Contrast", ImageEnhance.Contrast, -1.0, 3.0).pack()
+
+root.mainloop()
diff --git a/Imaging/Scripts/explode.py b/Imaging/Scripts/explode.py
new file mode 100644
index 0000000..0445402
--- /dev/null
+++ b/Imaging/Scripts/explode.py
@@ -0,0 +1,107 @@
+#
+# The Python Imaging Library
+# $Id: explode.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# split an animation into a number of frame files
+#
+
+import Image
+import os, string, sys
+
+class Interval:
+
+ def __init__(self, interval = "0"):
+
+ self.setinterval(interval)
+
+ def setinterval(self, interval):
+
+ self.hilo = []
+
+ for s in string.split(interval, ","):
+ if not string.strip(s):
+ continue
+ try:
+ v = string.atoi(s)
+ if v < 0:
+ lo, hi = 0, -v
+ else:
+ lo = hi = v
+ except ValueError:
+ i = string.find(s, "-")
+ lo, hi = string.atoi(s[:i]), string.atoi(s[i+1:])
+
+ self.hilo.append((hi, lo))
+
+ if not self.hilo:
+ self.hilo = [(sys.maxint, 0)]
+
+ def __getitem__(self, index):
+
+ for hi, lo in self.hilo:
+ if hi >= index >= lo:
+ return 1
+ return 0
+
+# --------------------------------------------------------------------
+# main program
+
+html = 0
+
+if sys.argv[1:2] == ["-h"]:
+ html = 1
+ del sys.argv[1]
+
+if not sys.argv[2:]:
+ print
+ print "Syntax: python explode.py infile template [range]"
+ print
+ print "The template argument is used to construct the names of the"
+ print "individual frame files. The frames are numbered file001.ext,"
+ print "file002.ext, etc. You can insert %d to control the placement"
+ print "and syntax of the frame number."
+ print
+ print "The optional range argument specifies which frames to extract."
+ print "You can give one or more ranges like 1-10, 5, -15 etc. If"
+ print "omitted, all frames are extracted."
+ sys.exit(1)
+
+infile = sys.argv[1]
+outfile = sys.argv[2]
+
+frames = Interval(string.join(sys.argv[3:], ","))
+
+try:
+ # check if outfile contains a placeholder
+ outfile % 1
+except TypeError:
+ file, ext = os.path.splitext(outfile)
+ outfile = file + "%03d" + ext
+
+ix = 1
+
+im = Image.open(infile)
+
+if html:
+ file, ext = os.path.splitext(outfile)
+ html = open(file+".html", "w")
+ html.write("<html>\n<body>\n")
+
+while 1:
+
+ if frames[ix]:
+ im.save(outfile % ix)
+ print outfile % ix
+
+ if html:
+ html.write("<img src='%s'><br>\n" % outfile % ix)
+
+ try:
+ im.seek(ix)
+ except EOFError:
+ break
+
+ ix = ix + 1
+
+if html:
+ html.write("</body>\n</html>\n")
diff --git a/Imaging/Scripts/gifmaker.py b/Imaging/Scripts/gifmaker.py
new file mode 100644
index 0000000..f27f9b8
--- /dev/null
+++ b/Imaging/Scripts/gifmaker.py
@@ -0,0 +1,135 @@
+#
+# The Python Imaging Library
+# $Id: gifmaker.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# convert sequence format to GIF animation
+#
+# history:
+# 97-01-03 fl created
+#
+# Copyright (c) Secret Labs AB 1997. All rights reserved.
+# Copyright (c) Fredrik Lundh 1997.
+#
+# See the README file for information on usage and redistribution.
+#
+
+#
+# For special purposes, you can import this module and call
+# the makedelta or compress functions yourself. For example,
+# if you have an application that generates a sequence of
+# images, you can convert it to a GIF animation using some-
+# thing like the following code:
+#
+# import Image
+# import gifmaker
+#
+# sequence = []
+#
+# # generate sequence
+# for i in range(100):
+# im = <generate image i>
+# sequence.append(im)
+#
+# # write GIF animation
+# fp = open("out.gif", "wb")
+# gifmaker.makedelta(fp, sequence)
+# fp.close()
+#
+# Alternatively, use an iterator to generate the sequence, and
+# write data directly to a socket. Or something...
+#
+
+import Image, ImageChops
+import string
+
+from GifImagePlugin import getheader, getdata
+
+# --------------------------------------------------------------------
+# sequence iterator
+
+class image_sequence:
+ def __init__(self, im):
+ self.im = im
+ def __getitem__(self, ix):
+ try:
+ if ix:
+ self.im.seek(ix)
+ return self.im
+ except EOFError:
+ raise IndexError # end of sequence
+
+# --------------------------------------------------------------------
+# straightforward delta encoding
+
+def makedelta(fp, sequence):
+ """Convert list of image frames to a GIF animation file"""
+
+ frames = 0
+
+ previous = None
+
+ for im in sequence:
+
+ #
+ # FIXME: write graphics control block before each frame
+
+ if not previous:
+
+ # global header
+ for s in getheader(im) + getdata(im):
+ fp.write(s)
+
+ else:
+
+ # delta frame
+ delta = ImageChops.subtract_modulo(im, previous)
+
+ bbox = delta.getbbox()
+
+ if bbox:
+
+ # compress difference
+ for s in getdata(im.crop(bbox), offset = bbox[:2]):
+ fp.write(s)
+
+ else:
+ # FIXME: what should we do in this case?
+ pass
+
+ previous = im.copy()
+
+ frames = frames + 1
+
+ fp.write(";")
+
+ return frames
+
+# --------------------------------------------------------------------
+# main hack
+
+def compress(infile, outfile):
+
+ # open input image, and force loading of first frame
+ im = Image.open(infile)
+ im.load()
+
+ # open output file
+ fp = open(outfile, "wb")
+
+ seq = image_sequence(im)
+
+ makedelta(fp, seq)
+
+ fp.close()
+
+
+if __name__ == "__main__":
+
+ import sys
+
+ if len(sys.argv) < 3:
+ print "GIFMAKER -- create GIF animations"
+ print "Usage: gifmaker infile outfile"
+ sys.exit(1)
+
+ compress(sys.argv[1], sys.argv[2])
diff --git a/Imaging/Scripts/image2py.py b/Imaging/Scripts/image2py.py
new file mode 100644
index 0000000..f769a7f
--- /dev/null
+++ b/Imaging/Scripts/image2py.py
@@ -0,0 +1,125 @@
+#
+# The Python Imaging Library
+# $Id: image2py.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# convert an image to a Python module
+#
+# to use the module, import it and access the "IMAGE" variable
+#
+# import img1
+# im = img1.IMAGE
+#
+# the variable name can be changed with the -n option
+#
+# note that the application using this module must include JPEG
+# and/or ZIP decoders, unless the -u option is used.
+#
+# Copyright (c) Secret Labs AB 1997. All rights reserved.
+# Copyright (c) Fredrik Lundh 1997.
+#
+# See the README file for information on usage and redistribution.
+#
+
+import Image
+import getopt, string, StringIO, sys
+
+octdigits = "01234567"
+
+def usage():
+ print "image2py 0.1/97-01-03 -- convert image to python module"
+ print
+ print "Usage: image2py [options] imagefile pyfile"
+ print
+ print "Options:"
+ print " -n <name> set variable name (default is 'IMAGE')"
+ print " -l use lossy compression (JPEG) if suitable"
+ print " -u disable compression"
+ print
+ print "Provided you use distinct variable names, the output"
+ print "files can be concatenated into one large module file."
+ sys.exit(1)
+
+try:
+ opt, argv = getopt.getopt(sys.argv[1:], "n:lu")
+except getopt.error, v:
+ usage()
+
+name = "IMAGE"
+lossy = 0
+compress = 1
+
+for o, a in opt:
+ if o == "-n":
+ name = a
+ elif o == "-l":
+ lossy = 1
+ elif o == "-u":
+ compress = 0
+
+if len(argv) != 2:
+ usage()
+
+# --------------------------------------------------------------------
+# convert image to string
+
+im = Image.open(argv[0])
+
+if im.format == "JPEG" and compress:
+
+ # store as is
+ data = open(argv[0], "rb").read()
+
+else:
+
+ # load and store as PNG
+ fp = StringIO.StringIO()
+
+ if compress:
+ if lossy and im.mode in ["L", "RGB"]:
+ im.save(fp, "JPEG")
+ else:
+ im.convert("RGB").save(fp, "PNG")
+ else:
+ im.save(fp, "PPM") # FIXME: won't work with "P" images
+
+ data = fp.getvalue()
+
+# --------------------------------------------------------------------
+# convert string to python module (this is not very fast...)
+
+fp = open(argv[1], "w")
+
+data = repr(data)
+
+fp.write("# generated by image2py %s\n" % argv[0])
+fp.write("import Image, StringIO\n")
+
+word = "%s = Image.open(StringIO.StringIO('" % name
+
+fp.write(word)
+c = len(word)
+
+i = 1
+while i < len(data)-1:
+ if data[i] != "\\":
+ word = data[i]
+ i = i + 1
+ else:
+ if data[i+1] in octdigits:
+ for n in range(2, 5):
+ if data[i+n] not in octdigits:
+ break
+ word = data[i:i+n]
+ i = i + n
+ else:
+ word = data[i:i+2]
+ i = i + 2
+ l = len(word)
+ if c + l >= 78-1:
+ # fp.write("'\n'")
+ fp.write("\\\n")
+ c = 0
+ fp.write(word)
+ c = c + l
+
+fp.write("'))\n")
diff --git a/Imaging/Scripts/painter.py b/Imaging/Scripts/painter.py
new file mode 100644
index 0000000..bf7a114
--- /dev/null
+++ b/Imaging/Scripts/painter.py
@@ -0,0 +1,72 @@
+#
+# The Python Imaging Library
+# $Id: painter.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# this demo script illustrates pasting into an already displayed
+# photoimage. note that the current version of Tk updates the whole
+# image everytime we paste, so to get decent performance, we split
+# the image into a set of tiles.
+#
+
+from Tkinter import *
+import Image, ImageTk
+import sys
+
+#
+# painter widget
+
+class PaintCanvas(Canvas):
+ def __init__(self, master, image):
+ Canvas.__init__(self, master, width=image.size[0], height=image.size[1])
+
+ # fill the canvas
+ self.tile = {}
+ self.tilesize = tilesize = 32
+ xsize, ysize = image.size
+ for x in range(0, xsize, tilesize):
+ for y in range(0, ysize, tilesize):
+ box = x, y, min(xsize, x+tilesize), min(ysize, y+tilesize)
+ tile = ImageTk.PhotoImage(image.crop(box))
+ self.create_image(x, y, image=tile, anchor=NW)
+ self.tile[(x,y)] = box, tile
+
+ self.image = image
+
+ self.bind("<B1-Motion>", self.paint)
+
+ def paint(self, event):
+ xy = event.x - 10, event.y - 10, event.x + 10, event.y + 10
+ im = self.image.crop(xy)
+
+ # process the image in some fashion
+ im = im.convert("L")
+
+ self.image.paste(im, xy)
+ self.repair(xy)
+
+ def repair(self, box):
+ # update canvas
+ dx = box[0] % self.tilesize
+ dy = box[1] % self.tilesize
+ for x in range(box[0]-dx, box[2]+1, self.tilesize):
+ for y in range(box[1]-dy, box[3]+1, self.tilesize):
+ try:
+ xy, tile = self.tile[(x, y)]
+ tile.paste(self.image.crop(xy))
+ except KeyError:
+ pass # outside the image
+ self.update_idletasks()
+
+#
+# main
+
+root = Tk()
+
+im = Image.open(sys.argv[1])
+
+if im.mode != "RGB":
+ im = im.convert("RGB")
+
+PaintCanvas(root, im).pack()
+
+root.mainloop()
diff --git a/Imaging/Scripts/pilconvert.py b/Imaging/Scripts/pilconvert.py
new file mode 100644
index 0000000..176f2a6
--- /dev/null
+++ b/Imaging/Scripts/pilconvert.py
@@ -0,0 +1,96 @@
+#! /usr/local/bin/python
+#
+# The Python Imaging Library.
+# $Id: pilconvert.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# convert image files
+#
+# History:
+# 0.1 96-04-20 fl Created
+# 0.2 96-10-04 fl Use draft mode when converting images
+# 0.3 96-12-30 fl Optimize output (PNG, JPEG)
+# 0.4 97-01-18 fl Made optimize an option (PNG, JPEG)
+# 0.5 98-12-30 fl Fixed -f option (from Anthony Baxter)
+#
+
+import site
+import getopt, string, sys
+
+from PIL import Image
+
+def usage():
+ print "PIL Convert 0.5/1998-12-30 -- convert image files"
+ print "Usage: pilconvert [option] infile outfile"
+ print
+ print "Options:"
+ print
+ print " -c <format> convert to format (default is given by extension)"
+ print
+ print " -g convert to greyscale"
+ print " -p convert to palette image (using standard palette)"
+ print " -r convert to rgb"
+ print
+ print " -o optimize output (trade speed for size)"
+ print " -q <value> set compression quality (0-100, JPEG only)"
+ print
+ print " -f list supported file formats"
+ sys.exit(1)
+
+if len(sys.argv) == 1:
+ usage()
+
+try:
+ opt, argv = getopt.getopt(sys.argv[1:], "c:dfgopq:r")
+except getopt.error, v:
+ print v
+ sys.exit(1)
+
+format = None
+convert = None
+
+options = { }
+
+for o, a in opt:
+
+ if o == "-f":
+ Image.init()
+ id = Image.ID[:]
+ id.sort()
+ print "Supported formats (* indicates output format):"
+ for i in id:
+ if Image.SAVE.has_key(i):
+ print i+"*",
+ else:
+ print i,
+ sys.exit(1)
+
+ elif o == "-c":
+ format = a
+
+ if o == "-g":
+ convert = "L"
+ elif o == "-p":
+ convert = "P"
+ elif o == "-r":
+ convert = "RGB"
+
+ elif o == "-o":
+ options["optimize"] = 1
+ elif o == "-q":
+ options["quality"] = string.atoi(a)
+
+if len(argv) != 2:
+ usage()
+
+try:
+ im = Image.open(argv[0])
+ if convert and im.mode != convert:
+ im.draft(convert, im.size)
+ im = im.convert(convert)
+ if format:
+ apply(im.save, (argv[1], format), options)
+ else:
+ apply(im.save, (argv[1],), options)
+except:
+ print "cannot convert image",
+ print "(%s:%s)" % (sys.exc_type, sys.exc_value)
diff --git a/Imaging/Scripts/pildriver.py b/Imaging/Scripts/pildriver.py
new file mode 100644
index 0000000..089e0bd
--- /dev/null
+++ b/Imaging/Scripts/pildriver.py
@@ -0,0 +1,523 @@
+#!/usr/bin/env python
+"""PILdriver, an image-processing calculator using PIL.
+
+An instance of class PILDriver is essentially a software stack machine
+(Polish-notation interpreter) for sequencing PIL image
+transformations. The state of the instance is the interpreter stack.
+
+The only method one will normally invoke after initialization is the
+`execute' method. This takes an argument list of tokens, pushes them
+onto the instance's stack, and then tries to clear the stack by
+successive evaluation of PILdriver operators. Any part of the stack
+not cleaned off persists and is part of the evaluation context for
+the next call of the execute method.
+
+PILDriver doesn't catch any exceptions, on the theory that these
+are actually diagnostic information that should be interpreted by
+the calling code.
+
+When called as a script, the command-line arguments are passed to
+a PILDriver instance. If there are no command-line arguments, the
+module runs an interactive interpreter, each line of which is split into
+space-separated tokens and passed to the execute method.
+
+In the method descriptions below, a first line beginning with the string
+`usage:' means this method can be invoked with the token that follows
+it. Following <>-enclosed arguments describe how the method interprets
+the entries on the stack. Each argument specification begins with a
+type specification: either `int', `float', `string', or `image'.
+
+All operations consume their arguments off the stack (use `dup' to
+keep copies around). Use `verbose 1' to see the stack state displayed
+before each operation.
+
+Usage examples:
+
+ `show crop 0 0 200 300 open test.png' loads test.png, crops out a portion
+of its upper-left-hand corner and displays the cropped portion.
+
+ `save rotated.png rotate 30 open test.tiff' loads test.tiff, rotates it
+30 degrees, and saves the result as rotated.png (in PNG format).
+"""
+# by Eric S. Raymond <esr@thyrsus.com>
+# $Id: pildriver.py 2813 2006-10-07 10:11:35Z fredrik $
+
+# TO DO:
+# 1. Add PILFont capabilities, once that's documented.
+# 2. Add PILDraw operations.
+# 3. Add support for composing and decomposing multiple-image files.
+#
+
+import Image, string
+
+class PILDriver:
+
+ verbose = 0
+
+ def do_verbose(self):
+ """usage: verbose <int:num>
+
+ Set verbosity flag from top of stack.
+ """
+ self.verbose = self.do_pop()
+
+ # The evaluation stack (internal only)
+
+ stack = [] # Stack of pending operations
+
+ def push(self, item):
+ "Push an argument onto the evaluation stack."
+ self.stack = [item] + self.stack
+
+ def top(self):
+ "Return the top-of-stack element."
+ return self.stack[0]
+
+ # Stack manipulation (callable)
+
+ def do_clear(self):
+ """usage: clear
+
+ Clear the stack.
+ """
+ self.stack = []
+
+ def do_pop(self):
+ """usage: pop
+
+ Discard the top element on the stack.
+ """
+ top = self.stack[0]
+ self.stack = self.stack[1:]
+ return top
+
+ def do_dup(self):
+ """usage: dup
+
+ Duplicate the top-of-stack item.
+ """
+ if hasattr(self, 'format'): # If it's an image, do a real copy
+ dup = self.stack[0].copy()
+ else:
+ dup = self.stack[0]
+ self.stack = [dup] + self.stack
+
+ def do_swap(self):
+ """usage: swap
+
+ Swap the top-of-stack item with the next one down.
+ """
+ self.stack = [self.stack[1], self.stack[0]] + self.stack[2:]
+
+ # Image module functions (callable)
+
+ def do_new(self):
+ """usage: new <int:xsize> <int:ysize> <int:color>:
+
+ Create and push a greyscale image of given size and color.
+ """
+ xsize = int(self.do_pop())
+ ysize = int(self.do_pop())
+ color = int(self.do_pop())
+ self.push(Image.new("L", (xsize, ysize), color))
+
+ def do_open(self):
+ """usage: open <string:filename>
+
+ Open the indicated image, read it, push the image on the stack.
+ """
+ self.push(Image.open(self.do_pop()))
+
+ def do_blend(self):
+ """usage: blend <image:pic1> <image:pic2> <float:alpha>
+
+ Replace two images and an alpha with the blended image.
+ """
+ image1 = self.do_pop()
+ image2 = self.do_pop()
+ alpha = float(self.do_pop())
+ self.push(Image.blend(image1, image2, alpha))
+
+ def do_composite(self):
+ """usage: composite <image:pic1> <image:pic2> <image:mask>
+
+ Replace two images and a mask with their composite.
+ """
+ image1 = self.do_pop()
+ image2 = self.do_pop()
+ mask = self.do_pop()
+ self.push(Image.composite(image1, image2, mask))
+
+ def do_merge(self):
+ """usage: merge <string:mode> <image:pic1> [<image:pic2> [<image:pic3> [<image:pic4>]]]
+
+ Merge top-of stack images in a way described by the mode.
+ """
+ mode = self.do_pop()
+ bandlist = []
+ for band in mode:
+ bandlist.append(self.do_pop())
+ self.push(Image.merge(mode, bandlist))
+
+ # Image class methods
+
+ def do_convert(self):
+ """usage: convert <string:mode> <image:pic1>
+
+ Convert the top image to the given mode.
+ """
+ mode = self.do_pop()
+ image = self.do_pop()
+ self.push(image.convert(mode))
+
+ def do_copy(self):
+ """usage: copy <image:pic1>
+
+ Make and push a true copy of the top image.
+ """
+ self.dup()
+
+ def do_crop(self):
+ """usage: crop <int:left> <int:upper> <int:right> <int:lower> <image:pic1>
+
+ Crop and push a rectangular region from the current image.
+ """
+ left = int(self.do_pop())
+ upper = int(self.do_pop())
+ right = int(self.do_pop())
+ lower = int(self.do_pop())
+ image = self.do_pop()
+ self.push(image.crop((left, upper, right, lower)))
+
+ def do_draft(self):
+ """usage: draft <string:mode> <int:xsize> <int:ysize>
+
+ Configure the loader for a given mode and size.
+ """
+ mode = self.do_pop()
+ xsize = int(self.do_pop())
+ ysize = int(self.do_pop())
+ self.push(self.draft(mode, (xsize, ysize)))
+
+ def do_filter(self):
+ """usage: filter <string:filtername> <image:pic1>
+
+ Process the top image with the given filter.
+ """
+ import ImageFilter
+ filter = eval("ImageFilter." + string.upper(self.do_pop()))
+ image = self.do_pop()
+ self.push(image.filter(filter))
+
+ def do_getbbox(self):
+ """usage: getbbox
+
+ Push left, upper, right, and lower pixel coordinates of the top image.
+ """
+ bounding_box = self.do_pop().getbbox()
+ self.push(bounding_box[3])
+ self.push(bounding_box[2])
+ self.push(bounding_box[1])
+ self.push(bounding_box[0])
+
+ def do_getextrema(self):
+ """usage: extrema
+
+ Push minimum and maximum pixel values of the top image.
+ """
+ extrema = self.do_pop().extrema()
+ self.push(extrema[1])
+ self.push(extrema[0])
+
+ def do_offset(self):
+ """usage: offset <int:xoffset> <int:yoffset> <image:pic1>
+
+ Offset the pixels in the top image.
+ """
+ xoff = int(self.do_pop())
+ yoff = int(self.do_pop())
+ image = self.do_pop()
+ self.push(image.offset(xoff, yoff))
+
+ def do_paste(self):
+ """usage: paste <image:figure> <int:xoffset> <int:yoffset> <image:ground>
+
+ Paste figure image into ground with upper left at given offsets.
+ """
+ figure = self.do_pop()
+ xoff = int(self.do_pop())
+ yoff = int(self.do_pop())
+ ground = self.do_pop()
+ if figure.mode == "RGBA":
+ ground.paste(figure, (xoff, yoff), figure)
+ else:
+ ground.paste(figure, (xoff, yoff))
+ self.push(ground)
+
+ def do_resize(self):
+ """usage: resize <int:xsize> <int:ysize> <image:pic1>
+
+ Resize the top image.
+ """
+ ysize = int(self.do_pop())
+ xsize = int(self.do_pop())
+ image = self.do_pop()
+ self.push(image.resize((xsize, ysize)))
+
+ def do_rotate(self):
+ """usage: rotate <int:angle> <image:pic1>
+
+ Rotate image through a given angle
+ """
+ angle = int(self.do_pop())
+ image = self.do_pop()
+ self.push(image.rotate(angle))
+
+ def do_save(self):
+ """usage: save <string:filename> <image:pic1>
+
+ Save image with default options.
+ """
+ filename = self.do_pop()
+ image = self.do_pop()
+ image.save(filename)
+
+ def do_save2(self):
+ """usage: save2 <string:filename> <string:options> <image:pic1>
+
+ Save image with specified options.
+ """
+ filename = self.do_pop()
+ options = self.do_pop()
+ image = self.do_pop()
+ image.save(filename, None, options)
+
+ def do_show(self):
+ """usage: show <image:pic1>
+
+ Display and pop the top image.
+ """
+ self.do_pop().show()
+
+ def do_thumbnail(self):
+ """usage: thumbnail <int:xsize> <int:ysize> <image:pic1>
+
+ Modify the top image in the stack to contain a thumbnail of itself.
+ """
+ ysize = int(self.do_pop())
+ xsize = int(self.do_pop())
+ self.top().thumbnail((xsize, ysize))
+
+ def do_transpose(self):
+ """usage: transpose <string:operator> <image:pic1>
+
+ Transpose the top image.
+ """
+ transpose = string.upper(self.do_pop())
+ image = self.do_pop()
+ self.push(image.transpose(transpose))
+
+ # Image attributes
+
+ def do_format(self):
+ """usage: format <image:pic1>
+
+ Push the format of the top image onto the stack.
+ """
+ self.push(self.pop().format)
+
+ def do_mode(self):
+ """usage: mode <image:pic1>
+
+ Push the mode of the top image onto the stack.
+ """
+ self.push(self.pop().mode)
+
+ def do_size(self):
+ """usage: size <image:pic1>
+
+ Push the image size on the stack as (y, x).
+ """
+ size = self.pop().size
+ self.push(size[0])
+ self.push(size[1])
+
+ # ImageChops operations
+
+ def do_invert(self):
+ """usage: invert <image:pic1>
+
+ Invert the top image.
+ """
+ import ImageChops
+ self.push(ImageChops.invert(self.do_pop()))
+
+ def do_lighter(self):
+ """usage: lighter <image:pic1> <image:pic2>
+
+ Pop the two top images, push an image of the lighter pixels of both.
+ """
+ import ImageChops
+ image1 = self.do_pop()
+ image2 = self.do_pop()
+ self.push(ImageChops.lighter(image1, image2))
+
+ def do_darker(self):
+ """usage: darker <image:pic1> <image:pic2>
+
+ Pop the two top images, push an image of the darker pixels of both.
+ """
+ import ImageChops
+ image1 = self.do_pop()
+ image2 = self.do_pop()
+ self.push(ImageChops.darker(image1, image2))
+
+ def do_difference(self):
+ """usage: difference <image:pic1> <image:pic2>
+
+ Pop the two top images, push the difference image
+ """
+ import ImageChops
+ image1 = self.do_pop()
+ image2 = self.do_pop()
+ self.push(ImageChops.difference(image1, image2))
+
+ def do_multiply(self):
+ """usage: multiply <image:pic1> <image:pic2>
+
+ Pop the two top images, push the multiplication image.
+ """
+ import ImageChops
+ image1 = self.do_pop()
+ image2 = self.do_pop()
+ self.push(ImageChops.multiply(image1, image2))
+
+ def do_screen(self):
+ """usage: screen <image:pic1> <image:pic2>
+
+ Pop the two top images, superimpose their inverted versions.
+ """
+ import ImageChops
+ image2 = self.do_pop()
+ image1 = self.do_pop()
+ self.push(ImageChops.screen(image1, image2))
+
+ def do_add(self):
+ """usage: add <image:pic1> <image:pic2> <int:offset> <float:scale>
+
+ Pop the two top images, produce the scaled sum with offset.
+ """
+ import ImageChops
+ image1 = self.do_pop()
+ image2 = self.do_pop()
+ scale = float(self.do_pop())
+ offset = int(self.do_pop())
+ self.push(ImageChops.add(image1, image2, scale, offset))
+
+ def do_subtract(self):
+ """usage: subtract <image:pic1> <image:pic2> <int:offset> <float:scale>
+
+ Pop the two top images, produce the scaled difference with offset.
+ """
+ import ImageChops
+ image1 = self.do_pop()
+ image2 = self.do_pop()
+ scale = float(self.do_pop())
+ offset = int(self.do_pop())
+ self.push(ImageChops.subtract(image1, image2, scale, offset))
+
+ # ImageEnhance classes
+
+ def do_color(self):
+ """usage: color <image:pic1>
+
+ Enhance color in the top image.
+ """
+ import ImageEnhance
+ factor = float(self.do_pop())
+ image = self.do_pop()
+ enhancer = ImageEnhance.Color(image)
+ self.push(enhancer.enhance(factor))
+
+ def do_contrast(self):
+ """usage: contrast <image:pic1>
+
+ Enhance contrast in the top image.
+ """
+ import ImageEnhance
+ factor = float(self.do_pop())
+ image = self.do_pop()
+ enhancer = ImageEnhance.Color(image)
+ self.push(enhancer.enhance(factor))
+
+ def do_brightness(self):
+ """usage: brightness <image:pic1>
+
+ Enhance brightness in the top image.
+ """
+ import ImageEnhance
+ factor = float(self.do_pop())
+ image = self.do_pop()
+ enhancer = ImageEnhance.Color(image)
+ self.push(enhancer.enhance(factor))
+
+ def do_sharpness(self):
+ """usage: sharpness <image:pic1>
+
+ Enhance sharpness in the top image.
+ """
+ import ImageEnhance
+ factor = float(self.do_pop())
+ image = self.do_pop()
+ enhancer = ImageEnhance.Color(image)
+ self.push(enhancer.enhance(factor))
+
+ # The interpreter loop
+
+ def execute(self, list):
+ "Interpret a list of PILDriver commands."
+ list.reverse()
+ while len(list) > 0:
+ self.push(list[0])
+ list = list[1:]
+ if self.verbose:
+ print "Stack: " + `self.stack`
+ top = self.top()
+ if type(top) != type(""):
+ continue;
+ funcname = "do_" + top
+ if not hasattr(self, funcname):
+ continue
+ else:
+ self.do_pop()
+ func = getattr(self, funcname)
+ func()
+
+if __name__ == '__main__':
+ import sys
+ try:
+ import readline
+ except ImportError:
+ pass # not available on all platforms
+
+ # If we see command-line arguments, interpret them as a stack state
+ # and execute. Otherwise go interactive.
+
+ driver = PILDriver()
+ if len(sys.argv[1:]) > 0:
+ driver.execute(sys.argv[1:])
+ else:
+ print "PILDriver says hello."
+ while 1:
+ try:
+ line = raw_input('pildriver> ');
+ except EOFError:
+ print "\nPILDriver says goodbye."
+ break
+ driver.execute(string.split(line))
+ print driver.stack
+
+# The following sets edit modes for GNU EMACS
+# Local Variables:
+# mode:python
+# End:
diff --git a/Imaging/Scripts/pilfile.py b/Imaging/Scripts/pilfile.py
new file mode 100644
index 0000000..a634032
--- /dev/null
+++ b/Imaging/Scripts/pilfile.py
@@ -0,0 +1,94 @@
+#! /usr/local/bin/python
+#
+# The Python Imaging Library.
+# $Id: pilfile.py 2813 2006-10-07 10:11:35Z fredrik $
+#
+# a utility to identify image files
+#
+# this script identifies image files, extracting size and
+# pixel mode information for known file formats. Note that
+# you don't need the PIL C extension to use this module.
+#
+# History:
+# 0.0 1995-09-01 fl Created
+# 0.1 1996-05-18 fl Modified options, added debugging mode
+# 0.2 1996-12-29 fl Added verify mode
+# 0.3 1999-06-05 fl Don't mess up on class exceptions (1.5.2 and later)
+# 0.4 2003-09-30 fl Expand wildcards on Windows; robustness tweaks
+#
+
+import site
+import getopt, glob, sys
+
+from PIL import Image
+
+if len(sys.argv) == 1:
+ print "PIL File 0.4/2003-09-30 -- identify image files"
+ print "Usage: pilfile [option] files..."
+ print "Options:"
+ print " -f list supported file formats"
+ print " -i show associated info and tile data"
+ print " -v verify file headers"
+ print " -q quiet, don't warn for unidentified/missing/broken files"
+ sys.exit(1)
+
+try:
+ opt, args = getopt.getopt(sys.argv[1:], "fqivD")
+except getopt.error, v:
+ print v
+ sys.exit(1)
+
+verbose = quiet = verify = 0
+
+for o, a in opt:
+ if o == "-f":
+ Image.init()
+ id = Image.ID[:]
+ id.sort()
+ print "Supported formats:"
+ for i in id:
+ print i,
+ sys.exit(1)
+ elif o == "-i":
+ verbose = 1
+ elif o == "-q":
+ quiet = 1
+ elif o == "-v":
+ verify = 1
+ elif o == "-D":
+ Image.DEBUG = Image.DEBUG + 1
+
+def globfix(files):
+ # expand wildcards where necessary
+ if sys.platform == "win32":
+ out = []
+ for file in files:
+ if glob.has_magic(file):
+ out.extend(glob.glob(file))
+ else:
+ out.append(file)
+ return out
+ return files
+
+for file in globfix(args):
+ try:
+ im = Image.open(file)
+ print "%s:" % file, im.format, "%dx%d" % im.size, im.mode,
+ if verbose:
+ print im.info, im.tile,
+ print
+ if verify:
+ try:
+ im.verify()
+ except:
+ if not quiet:
+ print "failed to verify image",
+ print "(%s:%s)" % (sys.exc_type, sys.exc_value)
+ except IOError, v:
+ if not quiet:
+ print file, "failed:", v
+ except:
+ import traceback
+ if not quiet:
+ print file, "failed:", "unexpected error"
+ traceback.print_exc(file=sys.stdout)
diff --git a/Imaging/Scripts/pilfont.py b/Imaging/Scripts/pilfont.py
new file mode 100644
index 0000000..b475463
--- /dev/null
+++ b/Imaging/Scripts/pilfont.py
@@ -0,0 +1,54 @@
+#
+# The Python Imaging Library
+# $Id: pilfont.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# PIL raster font compiler
+#
+# history:
+# 1997-08-25 fl created
+# 2002-03-10 fl use "from PIL import"
+#
+
+VERSION = "0.4"
+
+import site
+import glob, os, sys
+
+# drivers
+from PIL import BdfFontFile
+from PIL import PcfFontFile
+
+if len(sys.argv) <= 1:
+ print "PILFONT", VERSION, "-- PIL font compiler."
+ print
+ print "Usage: pilfont fontfiles..."
+ print
+ print "Convert given font files to the PIL raster font format."
+ print "This version of pilfont supports X BDF and PCF fonts."
+ sys.exit(1)
+
+files = []
+for f in sys.argv[1:]:
+ files = files + glob.glob(f)
+
+for f in files:
+
+ print f + "...",
+
+ try:
+
+ fp = open(f, "rb")
+
+ try:
+ p = PcfFontFile.PcfFontFile(fp)
+ except SyntaxError:
+ fp.seek(0)
+ p = BdfFontFile.BdfFontFile(fp)
+
+ p.save(f)
+
+ except (SyntaxError, IOError):
+ print "failed"
+
+ else:
+ print "OK"
diff --git a/Imaging/Scripts/pilprint.py b/Imaging/Scripts/pilprint.py
new file mode 100644
index 0000000..222cbff
--- /dev/null
+++ b/Imaging/Scripts/pilprint.py
@@ -0,0 +1,93 @@
+#! /usr/local/bin/python
+#
+# The Python Imaging Library.
+# $Id: pilprint.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# print image files to postscript printer
+#
+# History:
+# 0.1 1996-04-20 fl Created
+# 0.2 1996-10-04 fl Use draft mode when converting.
+# 0.3 2003-05-06 fl Fixed a typo or two.
+#
+
+VERSION = "pilprint 0.3/2003-05-05"
+
+import Image
+import PSDraw
+
+letter = ( 1.0*72, 1.0*72, 7.5*72, 10.0*72 )
+
+def description(file, image):
+ import os
+ title = os.path.splitext(os.path.split(file)[1])[0]
+ format = " (%dx%d "
+ if image.format:
+ format = " (" + image.format + " %dx%d "
+ return title + format % image.size + image.mode + ")"
+
+import getopt, os, sys
+
+if len(sys.argv) == 1:
+ print "PIL Print 0.2a1/96-10-04 -- print image files"
+ print "Usage: pilprint files..."
+ print "Options:"
+ print " -c colour printer (default is monochrome)"
+ print " -p print via lpr (default is stdout)"
+ print " -P <printer> same as -p but use given printer"
+ sys.exit(1)
+
+try:
+ opt, argv = getopt.getopt(sys.argv[1:], "cdpP:")
+except getopt.error, v:
+ print v
+ sys.exit(1)
+
+printer = None # print to stdout
+monochrome = 1 # reduce file size for most common case
+
+for o, a in opt:
+ if o == "-d":
+ # debug: show available drivers
+ Image.init()
+ print Image.ID
+ sys.exit(1)
+ elif o == "-c":
+ # colour printer
+ monochrome = 0
+ elif o == "-p":
+ # default printer channel
+ printer = "lpr"
+ elif o == "-P":
+ # printer channel
+ printer = "lpr -P%s" % a
+
+for file in argv:
+ try:
+
+ im = Image.open(file)
+
+ title = description(file, im)
+
+ if monochrome and im.mode not in ["1", "L"]:
+ im.draft("L", im.size)
+ im = im.convert("L")
+
+ if printer:
+ fp = os.popen(printer, "w")
+ else:
+ fp = sys.stdout
+
+ ps = PSDraw.PSDraw(fp)
+
+ ps.begin_document()
+ ps.setfont("Helvetica-Narrow-Bold", 18)
+ ps.text((letter[0], letter[3]+24), title)
+ ps.setfont("Helvetica-Narrow-Bold", 8)
+ ps.text((letter[0], letter[1]-30), VERSION)
+ ps.image(letter, im)
+ ps.end_document()
+
+ except:
+ print "cannot print image",
+ print "(%s:%s)" % (sys.exc_type, sys.exc_value)
diff --git a/Imaging/Scripts/player.py b/Imaging/Scripts/player.py
new file mode 100644
index 0000000..b6ef256
--- /dev/null
+++ b/Imaging/Scripts/player.py
@@ -0,0 +1,121 @@
+#
+# The Python Imaging Library
+# $Id: player.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+
+from Tkinter import *
+import Image, ImageTk
+import sys
+
+
+Image.DEBUG = 0
+
+
+# --------------------------------------------------------------------
+# experimental: support ARG animation scripts
+
+import ArgImagePlugin
+
+def applet_hook(animation, images):
+ app = animation(animation_display, images)
+ app.run()
+
+ArgImagePlugin.APPLET_HOOK = applet_hook
+
+class AppletDisplay:
+ def __init__(self, ui):
+ self.__ui = ui
+ def paste(self, im, bbox):
+ self.__ui.image.paste(im, bbox)
+ def update(self):
+ self.__ui.update_idletasks()
+
+# --------------------------------------------------------------------
+# an image animation player
+
+class UI(Label):
+
+ def __init__(self, master, im):
+ if type(im) == type([]):
+ # list of images
+ self.im = im[1:]
+ im = self.im[0]
+ else:
+ # sequence
+ self.im = im
+
+ if im.mode == "1":
+ self.image = ImageTk.BitmapImage(im, foreground="white")
+ else:
+ self.image = ImageTk.PhotoImage(im)
+
+ # APPLET SUPPORT (very crude, and not 100% safe)
+ global animation_display
+ animation_display = AppletDisplay(self)
+
+ Label.__init__(self, master, image=self.image, bg="black", bd=0)
+
+ self.update()
+
+ try:
+ duration = im.info["duration"]
+ except KeyError:
+ duration = 100
+ self.after(duration, self.next)
+
+ def next(self):
+
+ if type(self.im) == type([]):
+
+ try:
+ im = self.im[0]
+ del self.im[0]
+ self.image.paste(im)
+ except IndexError:
+ return # end of list
+
+ else:
+
+ try:
+ im = self.im
+ im.seek(im.tell() + 1)
+ self.image.paste(im)
+ except EOFError:
+ return # end of file
+
+ try:
+ duration = im.info["duration"]
+ except KeyError:
+ duration = 100
+ self.after(duration, self.next)
+
+ self.update_idletasks()
+
+
+# --------------------------------------------------------------------
+# script interface
+
+if __name__ == "__main__":
+
+ if not sys.argv[1:]:
+ print "Syntax: python player.py imagefile(s)"
+ sys.exit(1)
+
+ filename = sys.argv[1]
+
+ root = Tk()
+ root.title(filename)
+
+ if len(sys.argv) > 2:
+ # list of images
+ print "loading..."
+ im = []
+ for filename in sys.argv[1:]:
+ im.append(Image.open(filename))
+ else:
+ # sequence
+ im = Image.open(filename)
+
+ UI(root, im).pack()
+
+ root.mainloop()
diff --git a/Imaging/Scripts/thresholder.py b/Imaging/Scripts/thresholder.py
new file mode 100644
index 0000000..be5cbd4
--- /dev/null
+++ b/Imaging/Scripts/thresholder.py
@@ -0,0 +1,68 @@
+#
+# The Python Imaging Library
+# $Id: thresholder.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+# this demo script illustrates how a 1-bit BitmapImage can be used
+# as a dynamically updated overlay
+#
+
+from Tkinter import *
+import Image, ImageTk
+import sys
+
+#
+# an image viewer
+
+class UI(Frame):
+ def __init__(self, master, im, value = 128):
+ Frame.__init__(self, master)
+
+ self.image = im
+ self.value = value
+
+ self.canvas = Canvas(self, width=im.size[0], height=im.size[1])
+ self.backdrop = ImageTk.PhotoImage(im)
+ self.canvas.create_image(0, 0, image=self.backdrop, anchor=NW)
+ self.canvas.pack()
+
+ scale = Scale(self, orient=HORIZONTAL, from_=0, to=255,
+ resolution=1, command=self.update, length=256)
+ scale.set(value)
+ scale.bind("<ButtonRelease-1>", self.redraw)
+ scale.pack()
+
+ # uncomment the following line for instant feedback (might
+ # be too slow on some platforms)
+ # self.redraw()
+
+ def update(self, value):
+ self.value = eval(value)
+
+ self.redraw()
+
+ def redraw(self, event = None):
+
+ # create overlay (note the explicit conversion to mode "1")
+ im = self.image.point(lambda v,t=self.value: v>=t, "1")
+ self.overlay = ImageTk.BitmapImage(im, foreground="green")
+
+ # update canvas
+ self.canvas.delete("overlay")
+ self.canvas.create_image(0, 0, image=self.overlay, anchor=NW,
+ tags="overlay")
+
+# --------------------------------------------------------------------
+# main
+
+root = Tk()
+
+im = Image.open(sys.argv[1])
+
+if im.mode != "L":
+ im = im.convert("L")
+
+# im.thumbnail((320,200))
+
+UI(root, im).pack()
+
+root.mainloop()
diff --git a/Imaging/Scripts/viewer.py b/Imaging/Scripts/viewer.py
new file mode 100644
index 0000000..4027e17
--- /dev/null
+++ b/Imaging/Scripts/viewer.py
@@ -0,0 +1,46 @@
+#
+# The Python Imaging Library
+# $Id: viewer.py 2134 2004-10-06 08:55:20Z fredrik $
+#
+
+from Tkinter import *
+import Image, ImageTk
+
+#
+# an image viewer
+
+class UI(Label):
+
+ def __init__(self, master, im):
+
+ if im.mode == "1":
+ # bitmap image
+ self.image = ImageTk.BitmapImage(im, foreground="white")
+ Label.__init__(self, master, image=self.image, bg="black", bd=0)
+
+ else:
+ # photo image
+ self.image = ImageTk.PhotoImage(im)
+ Label.__init__(self, master, image=self.image, bd=0)
+
+#
+# script interface
+
+if __name__ == "__main__":
+
+ import sys
+
+ if not sys.argv[1:]:
+ print "Syntax: python viewer.py imagefile"
+ sys.exit(1)
+
+ filename = sys.argv[1]
+
+ root = Tk()
+ root.title(filename)
+
+ im = Image.open(filename)
+
+ UI(root, im).pack()
+
+ root.mainloop()
diff --git a/Imaging/Tk/booster.txt b/Imaging/Tk/booster.txt
new file mode 100644
index 0000000..2d78798
--- /dev/null
+++ b/Imaging/Tk/booster.txt
@@ -0,0 +1,108 @@
+====================================================================
+The Photoimage Booster Patch (for Windows 95/NT)
+====================================================================
+
+ This patch kit boosts performance for 16/24-bit displays. The
+first patch is required on Tk 4.2 (where it fixes the problems for
+16-bit displays) and later versions, with the exception for Tk 8.0b1
+where Sun added something similar themselves, only to remove it in
+8.0b2. By installing both patches, Tk's PhotoImage handling becomes
+much faster on both 16-bit and 24-bit displays. The patch has been
+tested with Tk 4.2 and 8.0.
+
+ Here's a benchmark, made with a sample program which loads two
+512x512 greyscale PGM's, and two 512x512 colour PPM's, and displays
+each of them in a separate toplevel windows. Tcl/Tk was compiled
+with Visual C 4.0, and run on a P100 under Win95. Image load times
+are not included in the timings:
+
+ 8-bit 16-bit 24-bit
+--------------------------------------------------------------------
+1. original 4.2 code 5.52 s 8.57 s 3.79 s
+2. booster patch 5.49 s 1.87 s 1.82 s
+
+ speedup None 4.6x 2.1x
+
+====================================================================
+
+Here's the patches:
+
+1. For portability and speed, the best thing under Windows is to
+treat 16-bit displays as if they were 24-bit. The Windows device
+drivers take care of the rest.
+
+ ----------------------------------------------------------------
+ If you have Tk 4.1 or Tk 8.0b1, you don't have to apply this
+ patch! It only applies to Tk 4.2, Tk 8.0a[12] and Tk 8.0b2.
+ ----------------------------------------------------------------
+
+In win/tkWinImage.c, change the following line in XCreateImage:
+
+ imagePtr->bits_per_pixel = depth;
+
+to
+
+/* ==================================================================== */
+/* The tk photo image booster patch -- patch section 1 */
+/* ==================================================================== */
+
+ if (visual->class == TrueColor)
+ /* true colour is stored as 3 bytes: (blue, green, red) */
+ imagePtr->bits_per_pixel = 24;
+ else
+ imagePtr->bits_per_pixel = depth;
+
+/* ==================================================================== */
+
+
+2. The DitherInstance implementation is not good. It's especially
+bad on highend truecolour displays. IMO, it should be rewritten from
+scratch (some other day...).
+
+ Anyway, the following band-aid makes the situation a little bit
+better under Windows. This hack trades some marginal quality (no
+dithering on 16-bit displays) for a dramatic performance boost.
+Requires patch 1, unless you're using Tk 4.1 or Tk 8.0b1.
+
+In generic/tkImgPhoto.c, add the #ifdef section to the DitherInstance
+function:
+
+ for (; height > 0; height -= nLines) {
+ if (nLines > height) {
+ nLines = height;
+ }
+ dstLinePtr = (unsigned char *) imagePtr->data;
+ yEnd = yStart + nLines;
+
+/* ==================================================================== */
+/* The tk photo image booster patch -- patch section 2 */
+/* ==================================================================== */
+
+#ifdef __WIN32__
+ if (colorPtr->visualInfo.class == TrueColor
+ && instancePtr->gamma == 1.0) {
+ /* Windows hicolor/truecolor booster */
+ for (y = yStart; y < yEnd; ++y) {
+ destBytePtr = dstLinePtr;
+ srcPtr = srcLinePtr;
+ for (x = xStart; x < xEnd; ++x) {
+ destBytePtr[0] = srcPtr[2];
+ destBytePtr[1] = srcPtr[1];
+ destBytePtr[2] = srcPtr[0];
+ destBytePtr += 3; srcPtr += 3;
+ }
+ srcLinePtr += lineLength;
+ dstLinePtr += bytesPerLine;
+ }
+ } else
+#endif
+
+/* ==================================================================== */
+
+ for (y = yStart; y < yEnd; ++y) {
+ srcPtr = srcLinePtr;
+ errPtr = errLinePtr;
+ destBytePtr = dstLinePtr;
+
+====================================================================
+last updated: 97-07-03/fl
diff --git a/Imaging/Tk/install.txt b/Imaging/Tk/install.txt
new file mode 100644
index 0000000..e24d363
--- /dev/null
+++ b/Imaging/Tk/install.txt
@@ -0,0 +1,41 @@
+====================================================================
+Using PIL With Tkinter
+====================================================================
+
+Starting with 1.0 final (release candidate 2 and later, to be
+precise), PIL can attach itself to Tkinter in flight. As a result,
+you no longer need to rebuild the Tkinter extension to be able to
+use PIL.
+
+However, if you cannot get the this to work on your platform, you
+can do it in the old way:
+
+* Adding Tkinter support
+
+1. Compile Python's _tkinter.c with the WITH_APPINIT and WITH_PIL
+ flags set, and link it with tkImaging.c and tkappinit.c. To
+ do this, copy the former to the Modules directory, and edit
+ the _tkinter line in Setup (or Setup.in) according to the
+ instructions in that file.
+
+ NOTE: if you have an old Python version, the tkappinit.c
+ file is not included by default. If this is the case, you
+ will have to add the following lines to tkappinit.c, after
+ the MOREBUTTONS stuff:
+
+ {
+ extern void TkImaging_Init(Tcl_Interp* interp);
+ TkImaging_Init(interp);
+ }
+
+ This registers a Tcl command called "PyImagingPhoto", which is
+ use to communicate between PIL and Tk's PhotoImage handler.
+
+ You must also change the _tkinter line in Setup (or Setup.in)
+ to something like:
+
+ _tkinter _tkinter.c tkImaging.c tkappinit.c -DWITH_APPINIT
+ -I/usr/local/include -L/usr/local/lib -ltk8.0 -ltcl8.0 -lX11
+
+
+
diff --git a/Imaging/Tk/pilbitmap.txt b/Imaging/Tk/pilbitmap.txt
new file mode 100644
index 0000000..e7c46c6
--- /dev/null
+++ b/Imaging/Tk/pilbitmap.txt
@@ -0,0 +1,149 @@
+====================================================================
+The PIL Bitmap Booster Patch
+====================================================================
+
+The pilbitmap booster patch greatly improves performance of the
+ImageTk.BitmapImage constructor. Unfortunately, the design of Tk
+doesn't allow us to do this from the tkImaging interface module, so
+you have to patch the Tk sources.
+
+Once installed, the ImageTk module will automatically detect this
+patch.
+
+(Note: this patch has been tested with Tk 8.0 on Win32 only, but it
+should work just fine on other platforms as well).
+
+1. To the beginning of TkGetBitmapData (in generic/tkImgBmap.c), add
+ the following stuff:
+
+------------------------------------------------------------------------
+ int width, height, numBytes, hotX, hotY;
+ char *p, *end, *expandedFileName;
+ ParseInfo pi;
+ char *data = NULL;
+ Tcl_DString buffer;
+
+/* ==================================================================== */
+/* The pilbitmap booster patch -- patch section */
+/* ==================================================================== */
+
+ char *PILGetBitmapData();
+
+ if (string) {
+ /* Is this a PIL bitmap reference? */
+ data = PILGetBitmapData(string, widthPtr, heightPtr, hotXPtr, hotYPtr);
+ if (data)
+ return data;
+ }
+
+/* ==================================================================== */
+
+ pi.string = string;
+ if (string == NULL) {
+ if (Tcl_IsSafe(interp)) {
+------------------------------------------------------------------------
+
+
+2. Append the following to the same file (you may wish to include
+Imaging.h instead of copying the struct declaration...)
+
+------------------------------------------------------------------------
+
+/* ==================================================================== */
+/* The pilbitmap booster patch -- code section */
+/* ==================================================================== */
+
+/* Imaging declaration boldly copied from Imaging.h (!) */
+
+typedef struct ImagingInstance *Imaging; /* a.k.a. ImagingImage :-) */
+
+typedef unsigned char UINT8;
+typedef int INT32;
+
+struct ImagingInstance {
+
+ /* Format */
+ char mode[4+1]; /* Band names ("1", "L", "P", "RGB", "RGBA", "CMYK") */
+ int type; /* Always 0 in this version */
+ int depth; /* Always 8 in this version */
+ int bands; /* Number of bands (1, 3, or 4) */
+ int xsize; /* Image dimension. */
+ int ysize;
+
+ /* Colour palette (for "P" images only) */
+ void* palette;
+
+ /* Data pointers */
+ UINT8 **image8; /* Set for 8-bit image (pixelsize=1). */
+ INT32 **image32; /* Set for 32-bit image (pixelsize=4). */
+
+ /* Internals */
+ char **image; /* Actual raster data. */
+ char *block; /* Set if data is allocated in a single block. */
+
+ int pixelsize; /* Size of a pixel, in bytes (1 or 4) */
+ int linesize; /* Size of a line, in bytes (xsize * pixelsize) */
+
+ /* Virtual methods */
+ void (*im_delete)(Imaging *);
+
+};
+
+/* The pilbitmap booster patch allows you to pass PIL images to the
+ Tk bitmap decoder. Passing images this way is much more efficient
+ than using the "tobitmap" method. */
+
+char *
+PILGetBitmapData(string, widthPtr, heightPtr, hotXPtr, hotYPtr)
+ char *string;
+ int *widthPtr, *heightPtr;
+ int *hotXPtr, *hotYPtr;
+{
+ char* data;
+ char* p;
+ int y;
+ Imaging im;
+
+ if (strncmp(string, "PIL:", 4) != 0)
+ return NULL;
+
+ im = (Imaging) atol(string + 4);
+
+ if (strcmp(im->mode, "1") != 0 && strcmp(im->mode, "L") != 0)
+ return NULL;
+
+ data = p = (char *) ckalloc((unsigned) ((im->xsize+7)/8) * im->ysize);
+
+ for (y = 0; y < im->ysize; y++) {
+ char* in = im->image8[y];
+ int i, m, b;
+ b = 0; m = 1;
+ for (i = 0; i < im->xsize; i++) {
+ if (in[i] != 0)
+ b |= m;
+ m <<= 1;
+ if (m == 256){
+ *p++ = b;
+ b = 0; m = 1;
+ }
+ }
+ if (m != 1)
+ *p++ = b;
+ }
+
+ *widthPtr = im->xsize;
+ *heightPtr = im->ysize;
+ *hotXPtr = -1;
+ *hotYPtr = -1;
+
+ return data;
+}
+
+/* ==================================================================== */
+
+------------------------------------------------------------------------
+
+3. Recompile Tk and relink the _tkinter module (where necessary).
+
+====================================================================
+Last updated: 97-05-17/fl
diff --git a/Imaging/Tk/tkImaging.c b/Imaging/Tk/tkImaging.c
new file mode 100644
index 0000000..5e37d05
--- /dev/null
+++ b/Imaging/Tk/tkImaging.c
@@ -0,0 +1,247 @@
+/*
+ * The Python Imaging Library.
+ * $Id: tkImaging.c,v 1.1 1996/05/09 22:11:39 fredrik Exp $
+ *
+ * TK interface for Python Imaging objects
+ *
+ * Copies (parts of) a named display memory to a photo image object.
+ * Also contains code to create an display memory. Under Tk, a
+ * display memory is simply an "L" or "RGB" image memory that is
+ * allocated in a single block.
+ *
+ * To use this module, add the following lines to your Tcl_AppInit
+ * function (in tkappinit.c). Put them after the calls to Tcl_Init
+ * and Tk_Init:
+ *
+ * {
+ * extern void TkImaging_Init(Tcl_Interp* interp);
+ * TkImaging_Init(interp);
+ * }
+ *
+ * This registers a Tcl command called "PyImagingPhoto", which
+ * is use to communicate between PIL and Tk's PhotoImage handler.
+ *
+ * Compile and link tkImaging.c with tkappinit.c and _tkinter
+ * (see the Setup file for details on how to use tkappinit.c).
+ * Note that _tkinter.c must be compiled with WITH_APPINIT.
+ *
+ * History:
+ * 1995-09-12 fl Created
+ * 1996-04-08 fl Ready for release
+ * 1997-05-09 fl Use command instead of image type
+ * 2001-03-18 fl Initialize alpha layer pointer (struct changed in 8.3)
+ * 2003-04-23 fl Fixed building for Tk 8.4.1 and later (Jack Jansen)
+ * 2004-06-24 fl Fixed building for Tk 8.4.6 and later.
+ *
+ * Copyright (c) 1997-2004 by Secret Labs AB
+ * Copyright (c) 1995-2004 by Fredrik Lundh
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+/* This is needed for (at least) Tk 8.4.1, otherwise the signature of
+** Tk_PhotoPutBlock changes.
+*/
+#define USE_COMPOSITELESS_PHOTO_PUT_BLOCK
+
+/* This is needed for (at least) Tk 8.4.6 and later, to avoid warnings
+ for the Tcl_CreateCommand command. */
+#define USE_COMPAT_CONST
+
+#include "tk.h"
+
+#include "Imaging.h"
+
+#include <stdlib.h>
+
+
+static Imaging
+ImagingFind(const char* name)
+{
+ long id;
+
+ /* FIXME: use CObject instead? */
+ id = atol(name);
+ if (!id)
+ return NULL;
+
+ return (Imaging) id;
+}
+
+
+static int
+PyImagingPhotoPut(ClientData clientdata, Tcl_Interp* interp,
+ int argc, char **argv)
+{
+ Imaging im;
+ Tk_PhotoHandle photo;
+ Tk_PhotoImageBlock block;
+
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "usage: ", argv[0],
+ " destPhoto srcImage", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ /* get Tcl PhotoImage handle */
+ photo = Tk_FindPhoto(interp, argv[1]);
+ if (photo == NULL) {
+ Tcl_AppendResult(
+ interp, "destination photo must exist", (char *) NULL
+ );
+ return TCL_ERROR;
+ }
+
+ /* get PIL Image handle */
+ im = ImagingFind(argv[2]);
+ if (!im) {
+ Tcl_AppendResult(interp, "bad name", (char*) NULL);
+ return TCL_ERROR;
+ }
+ if (!im->block) {
+ Tcl_AppendResult(interp, "bad display memory", (char*) NULL);
+ return TCL_ERROR;
+ }
+
+ /* Active region */
+#if 0
+ if (src_xoffset + xsize > im->xsize)
+ xsize = im->xsize - src_xoffset;
+ if (src_yoffset + ysize > im->ysize)
+ ysize = im->ysize - src_yoffset;
+ if (xsize < 0 || ysize < 0
+ || src_xoffset >= im->xsize
+ || src_yoffset >= im->ysize)
+ return TCL_OK;
+#endif
+
+ /* Mode */
+
+ if (strcmp(im->mode, "1") == 0 || strcmp(im->mode, "L") == 0) {
+ block.pixelSize = 1;
+ block.offset[0] = block.offset[1] = block.offset[2] = 0;
+ } else if (strncmp(im->mode, "RGB", 3) == 0) {
+ block.pixelSize = 4;
+ block.offset[0] = 0;
+ block.offset[1] = 1;
+ block.offset[2] = 2;
+ block.offset[3] = 0; /* no alpha (or reserved, under 8.2) */
+ } else {
+ Tcl_AppendResult(interp, "Bad mode", (char*) NULL);
+ return TCL_ERROR;
+ }
+
+ block.width = im->xsize;
+ block.height = im->ysize;
+ block.pitch = im->linesize;
+ block.pixelPtr = (unsigned char*) im->block;
+#if 0
+ block.pixelPtr = (unsigned char*) im->block +
+ src_yoffset * im->linesize +
+ src_xoffset * im->pixelsize;
+#endif
+
+ if (strcmp(im->mode, "RGBA") == 0) {
+ /* Copy non-transparent pixels to photo image */
+ int x, y;
+ Tk_PhotoImageBlock run;
+
+ /* Clear current contents */
+ Tk_PhotoBlank(photo);
+
+ /* Setup run descriptor */
+ run.height = 1;
+ run.pitch = block.pitch;
+ run.pixelSize = block.pixelSize;
+ run.offset[0] = 0;
+ run.offset[1] = 1;
+ run.offset[2] = 2;
+ run.offset[3] = 0; /* no alpha (or reserved, under 8.2) */
+
+ /* Copy opaque runs to photo image */
+ for (y = 0; y < block.height; y++) {
+ unsigned char* p = block.pixelPtr + y*block.pitch;
+ unsigned char* s = p;
+ int w = 0;
+ for (x = 0; x < block.width; x++) {
+ if (p[3]) {
+ /* opaque: add pixel to current run */
+ if (w == 0)
+ s = p;
+ w = w + 1;
+ } else if (s) {
+ /* copy run to photo image */
+ if (w > 0) {
+ run.width = w;
+ run.pixelPtr = s;
+ Tk_PhotoPutBlock(photo, &run, x-w, y, run.width, 1);
+ }
+ w = 0;
+ }
+ p += block.pixelSize;
+ }
+ if (w > 0) {
+ /* copy final run, if any */
+ run.width = w;
+ run.pixelPtr = s;
+ Tk_PhotoPutBlock(photo, &run, x-w, y, run.width, 1);
+ }
+ }
+
+ } else
+
+ /* Copy opaque block to photo image, and leave the rest to TK */
+ Tk_PhotoPutBlock(photo, &block, 0, 0, block.width, block.height);
+
+ return TCL_OK;
+}
+
+
+static int
+PyImagingPhotoGet(ClientData clientdata, Tcl_Interp* interp,
+ int argc, char **argv)
+{
+ Tk_PhotoHandle photo;
+ Tk_PhotoImageBlock block;
+
+ if (argc != 2) {
+ Tcl_AppendResult(interp, "usage: ", argv[0],
+ " srcPhoto", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ /* get Tcl PhotoImage handle */
+ photo = Tk_FindPhoto(interp, argv[1]);
+ if (photo == NULL) {
+ Tcl_AppendResult(
+ interp, "source photo must exist", (char *) NULL
+ );
+ return TCL_ERROR;
+ }
+
+ Tk_PhotoGetImage(photo, &block);
+
+ printf("pixelPtr = %p\n", block.pixelPtr);
+ printf("width = %d\n", block.width);
+ printf("height = %d\n", block.height);
+ printf("pitch = %d\n", block.pitch);
+ printf("pixelSize = %d\n", block.pixelSize);
+ printf("offset = %d %d %d %d\n", block.offset[0], block.offset[1],
+ block.offset[2], block.offset[3]);
+
+ Tcl_AppendResult(
+ interp, "this function is not yet support", (char *) NULL
+ );
+
+ return TCL_ERROR;
+}
+
+
+void
+TkImaging_Init(Tcl_Interp* interp)
+{
+ Tcl_CreateCommand(interp, "PyImagingPhoto", PyImagingPhotoPut,
+ (ClientData) 0, (Tcl_CmdDeleteProc*) NULL);
+ Tcl_CreateCommand(interp, "PyImagingPhotoGet", PyImagingPhotoGet,
+ (ClientData) 0, (Tcl_CmdDeleteProc*) NULL);
+}
diff --git a/Imaging/_imaging.c b/Imaging/_imaging.c
new file mode 100644
index 0000000..d5112ad
--- /dev/null
+++ b/Imaging/_imaging.c
@@ -0,0 +1,3149 @@
+/*
+ * The Python Imaging Library.
+ * $Id: _imaging.c 2935 2006-12-03 12:20:39Z fredrik $
+ *
+ * the imaging library bindings
+ *
+ * history:
+ * 1995-09-24 fl Created
+ * 1996-03-24 fl Ready for first public release (release 0.0)
+ * 1996-03-25 fl Added fromstring (for Jack's "img" library)
+ * 1996-03-28 fl Added channel operations
+ * 1996-03-31 fl Added point operation
+ * 1996-04-08 fl Added new/new_block/new_array factories
+ * 1996-04-13 fl Added decoders
+ * 1996-05-04 fl Added palette hack
+ * 1996-05-12 fl Compile cleanly as C++
+ * 1996-05-19 fl Added matrix conversions, gradient fills
+ * 1996-05-27 fl Added display_mode
+ * 1996-07-22 fl Added getbbox, offset
+ * 1996-07-23 fl Added sequence semantics
+ * 1996-08-13 fl Added logical operators, point mode
+ * 1996-08-16 fl Modified paste interface
+ * 1996-09-06 fl Added putdata methods, use abstract interface
+ * 1996-11-01 fl Added xbm encoder
+ * 1996-11-04 fl Added experimental path stuff, draw_lines, etc
+ * 1996-12-10 fl Added zip decoder, crc32 interface
+ * 1996-12-14 fl Added modulo arithmetics
+ * 1996-12-29 fl Added zip encoder
+ * 1997-01-03 fl Added fli and msp decoders
+ * 1997-01-04 fl Added experimental sun_rle and tga_rle decoders
+ * 1997-01-05 fl Added gif encoder, getpalette hack
+ * 1997-02-23 fl Added histogram mask
+ * 1997-05-12 fl Minor tweaks to match the IFUNC95 interface
+ * 1997-05-21 fl Added noise generator, spread effect
+ * 1997-06-05 fl Added mandelbrot generator
+ * 1997-08-02 fl Modified putpalette to coerce image mode if necessary
+ * 1998-01-11 fl Added INT32 support
+ * 1998-01-22 fl Fixed draw_points to draw the last point too
+ * 1998-06-28 fl Added getpixel, getink, draw_ink
+ * 1998-07-12 fl Added getextrema
+ * 1998-07-17 fl Added point conversion to arbitrary formats
+ * 1998-09-21 fl Added support for resampling filters
+ * 1998-09-22 fl Added support for quad transform
+ * 1998-12-29 fl Added support for arcs, chords, and pieslices
+ * 1999-01-10 fl Added some experimental arrow graphics stuff
+ * 1999-02-06 fl Added draw_bitmap, font acceleration stuff
+ * 2001-04-17 fl Fixed some egcs compiler nits
+ * 2001-09-17 fl Added screen grab primitives (win32)
+ * 2002-03-09 fl Added stretch primitive
+ * 2002-03-10 fl Fixed filter handling in rotate
+ * 2002-06-06 fl Added I, F, and RGB support to putdata
+ * 2002-06-08 fl Added rankfilter
+ * 2002-06-09 fl Added support for user-defined filter kernels
+ * 2002-11-19 fl Added clipboard grab primitives (win32)
+ * 2002-12-11 fl Added draw context
+ * 2003-04-26 fl Tweaks for Python 2.3 beta 1
+ * 2003-05-21 fl Added createwindow primitive (win32)
+ * 2003-09-13 fl Added thread section hooks
+ * 2003-09-15 fl Added expand helper
+ * 2003-09-26 fl Added experimental LA support
+ * 2004-02-21 fl Handle zero-size images in quantize
+ * 2004-06-05 fl Added ptr attribute (used to access Imaging objects)
+ * 2004-06-05 fl Don't crash when fetching pixels from zero-wide images
+ * 2004-09-17 fl Added getcolors
+ * 2004-10-04 fl Added modefilter
+ * 2005-10-02 fl Added access proxy
+ * 2006-06-18 fl Always draw last point in polyline
+ *
+ * Copyright (c) 1997-2006 by Secret Labs AB
+ * Copyright (c) 1995-2006 by Fredrik Lundh
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Python.h"
+
+#include "Imaging.h"
+
+
+/* Configuration stuff. Feel free to undef things you don't need. */
+#define WITH_IMAGECHOPS /* ImageChops support */
+#define WITH_IMAGEDRAW /* ImageDraw support */
+#define WITH_MAPPING /* use memory mapping to read some file formats */
+#define WITH_IMAGEPATH /* ImagePath stuff */
+#define WITH_ARROW /* arrow graphics stuff (experimental) */
+#define WITH_EFFECTS /* special effects */
+#define WITH_QUANTIZE /* quantization support */
+#define WITH_RANKFILTER /* rank filter */
+#define WITH_MODEFILTER /* mode filter */
+#define WITH_THREADING /* "friendly" threading support */
+
+#define WITH_DEBUG /* extra debugging interfaces */
+
+/* PIL Plus extensions */
+#undef WITH_CRACKCODE /* pil plus */
+
+#undef VERBOSE
+
+#define CLIP(x) ((x) <= 0 ? 0 : (x) < 256 ? (x) : 255)
+
+#define B16(p, i) ((((int)p[(i)]) << 8) + p[(i)+1])
+#define L16(p, i) ((((int)p[(i)+1]) << 8) + p[(i)])
+#define S16(v) ((v) < 32768 ? (v) : ((v) - 65536))
+
+#if PY_VERSION_HEX < 0x01060000
+#define PyObject_New PyObject_NEW
+#define PyObject_Del PyMem_DEL
+#endif
+
+#if PY_VERSION_HEX < 0x02050000
+#define ssizeargfunc intargfunc
+#define ssizessizeargfunc intintargfunc
+#define ssizeobjargproc intobjargproc
+#define ssizessizeobjargproc intintobjargproc
+#endif
+
+/* -------------------------------------------------------------------- */
+/* OBJECT ADMINISTRATION */
+/* -------------------------------------------------------------------- */
+
+typedef struct {
+ PyObject_HEAD
+ Imaging image;
+} ImagingObject;
+
+staticforward PyTypeObject Imaging_Type;
+
+#ifdef WITH_IMAGEDRAW
+
+typedef struct
+{
+ /* to write a character, cut out sxy from glyph data, place
+ at current position plus dxy, and advance by (dx, dy) */
+ int dx, dy;
+ int dx0, dy0, dx1, dy1;
+ int sx0, sy0, sx1, sy1;
+} Glyph;
+
+typedef struct {
+ PyObject_HEAD
+ ImagingObject* ref;
+ Imaging bitmap;
+ int ysize;
+ int baseline;
+ Glyph glyphs[256];
+} ImagingFontObject;
+
+staticforward PyTypeObject ImagingFont_Type;
+
+typedef struct {
+ PyObject_HEAD
+ ImagingObject* image;
+ UINT8 ink[4];
+ int blend;
+} ImagingDrawObject;
+
+staticforward PyTypeObject ImagingDraw_Type;
+
+#endif
+
+typedef struct {
+ PyObject_HEAD
+ ImagingObject* image;
+ int readonly;
+} PixelAccessObject;
+
+staticforward PyTypeObject PixelAccess_Type;
+
+PyObject*
+PyImagingNew(Imaging imOut)
+{
+ ImagingObject* imagep;
+
+ if (!imOut)
+ return NULL;
+
+ imagep = PyObject_New(ImagingObject, &Imaging_Type);
+ if (imagep == NULL) {
+ ImagingDelete(imOut);
+ return NULL;
+ }
+
+#ifdef VERBOSE
+ printf("imaging %p allocated\n", imagep);
+#endif
+
+ imagep->image = imOut;
+
+ return (PyObject*) imagep;
+}
+
+static void
+_dealloc(ImagingObject* imagep)
+{
+
+#ifdef VERBOSE
+ printf("imaging %p deleted\n", imagep);
+#endif
+
+ ImagingDelete(imagep->image);
+ PyObject_Del(imagep);
+}
+
+#define PyImaging_Check(op) ((op)->ob_type == &Imaging_Type)
+
+Imaging PyImaging_AsImaging(PyObject *op)
+{
+ if (!PyImaging_Check(op)) {
+ PyErr_BadInternalCall();
+ return NULL;
+ }
+
+ return ((ImagingObject *)op)->image;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* THREAD HANDLING */
+/* -------------------------------------------------------------------- */
+
+void ImagingSectionEnter(ImagingSectionCookie* cookie)
+{
+#ifdef WITH_THREADING
+ *cookie = (PyThreadState *) PyEval_SaveThread();
+#endif
+}
+
+void ImagingSectionLeave(ImagingSectionCookie* cookie)
+{
+#ifdef WITH_THREADING
+ PyEval_RestoreThread((PyThreadState*) *cookie);
+#endif
+}
+
+/* -------------------------------------------------------------------- */
+/* EXCEPTION REROUTING */
+/* -------------------------------------------------------------------- */
+
+/* error messages */
+static const char* must_be_sequence = "argument must be a sequence";
+static const char* wrong_mode = "unrecognized image mode";
+static const char* wrong_raw_mode = "unrecognized raw mode";
+static const char* outside_image = "image index out of range";
+static const char* outside_palette = "palette index out of range";
+static const char* no_palette = "image has no palette";
+static const char* readonly = "image is readonly";
+/* static const char* no_content = "image has no content"; */
+
+void *
+ImagingError_IOError(void)
+{
+ PyErr_SetString(PyExc_IOError, "error when accessing file");
+ return NULL;
+}
+
+void *
+ImagingError_MemoryError(void)
+{
+ return PyErr_NoMemory();
+}
+
+void *
+ImagingError_Mismatch(void)
+{
+ PyErr_SetString(PyExc_ValueError, "images do not match");
+ return NULL;
+}
+
+void *
+ImagingError_ModeError(void)
+{
+ PyErr_SetString(PyExc_ValueError, "image has wrong mode");
+ return NULL;
+}
+
+void *
+ImagingError_ValueError(const char *message)
+{
+ PyErr_SetString(
+ PyExc_ValueError,
+ (message) ? (char*) message : "unrecognized argument value"
+ );
+ return NULL;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* HELPERS */
+/* -------------------------------------------------------------------- */
+
+static int
+getbands(const char* mode)
+{
+ Imaging im;
+ int bands;
+
+ /* FIXME: add primitive to libImaging to avoid extra allocation */
+ im = ImagingNew(mode, 0, 0);
+ if (!im)
+ return -1;
+
+ bands = im->bands;
+
+ ImagingDelete(im);
+
+ return bands;
+}
+
+#define TYPE_UINT8 (0x100|sizeof(UINT8))
+#define TYPE_INT32 (0x200|sizeof(INT32))
+#define TYPE_FLOAT32 (0x300|sizeof(FLOAT32))
+#define TYPE_DOUBLE (0x400|sizeof(double))
+
+static void*
+getlist(PyObject* arg, int* length, const char* wrong_length, int type)
+{
+ int i, n;
+ void* list;
+
+ if (!PySequence_Check(arg)) {
+ PyErr_SetString(PyExc_TypeError, must_be_sequence);
+ return NULL;
+ }
+
+ n = PyObject_Length(arg);
+ if (length && wrong_length && n != *length) {
+ PyErr_SetString(PyExc_ValueError, wrong_length);
+ return NULL;
+ }
+
+ list = malloc(n * (type & 0xff));
+ if (!list) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ switch (type) {
+ case TYPE_UINT8:
+ if (PyList_Check(arg)) {
+ for (i = 0; i < n; i++) {
+ PyObject *op = PyList_GET_ITEM(arg, i);
+ int temp = PyInt_AsLong(op);
+ ((UINT8*)list)[i] = CLIP(temp);
+ }
+ } else {
+ for (i = 0; i < n; i++) {
+ PyObject *op = PySequence_GetItem(arg, i);
+ int temp = PyInt_AsLong(op);
+ Py_XDECREF(op);
+ ((UINT8*)list)[i] = CLIP(temp);
+ }
+ }
+ break;
+ case TYPE_INT32:
+ if (PyList_Check(arg)) {
+ for (i = 0; i < n; i++) {
+ PyObject *op = PyList_GET_ITEM(arg, i);
+ int temp = PyInt_AsLong(op);
+ ((INT32*)list)[i] = temp;
+ }
+ } else {
+ for (i = 0; i < n; i++) {
+ PyObject *op = PySequence_GetItem(arg, i);
+ int temp = PyInt_AsLong(op);
+ Py_XDECREF(op);
+ ((INT32*)list)[i] = temp;
+ }
+ }
+ break;
+ case TYPE_FLOAT32:
+ if (PyList_Check(arg)) {
+ for (i = 0; i < n; i++) {
+ PyObject *op = PyList_GET_ITEM(arg, i);
+ double temp = PyFloat_AsDouble(op);
+ ((FLOAT32*)list)[i] = (FLOAT32) temp;
+ }
+ } else {
+ for (i = 0; i < n; i++) {
+ PyObject *op = PySequence_GetItem(arg, i);
+ double temp = PyFloat_AsDouble(op);
+ Py_XDECREF(op);
+ ((FLOAT32*)list)[i] = (FLOAT32) temp;
+ }
+ }
+ break;
+ case TYPE_DOUBLE:
+ if (PyList_Check(arg)) {
+ for (i = 0; i < n; i++) {
+ PyObject *op = PyList_GET_ITEM(arg, i);
+ double temp = PyFloat_AsDouble(op);
+ ((double*)list)[i] = temp;
+ }
+ } else {
+ for (i = 0; i < n; i++) {
+ PyObject *op = PySequence_GetItem(arg, i);
+ double temp = PyFloat_AsDouble(op);
+ Py_XDECREF(op);
+ ((double*)list)[i] = temp;
+ }
+ }
+ break;
+ }
+
+ if (length)
+ *length = n;
+
+ PyErr_Clear();
+
+ return list;
+}
+
+static inline PyObject*
+getpixel(Imaging im, int x, int y)
+{
+ UINT8 *p;
+
+ if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) {
+ PyErr_SetString(PyExc_IndexError, outside_image);
+ return NULL;
+ }
+
+ /* single layer */
+ if (im->image8 != NULL) {
+ p = (UINT8*) &im->image8[y][x];
+ switch (im->type) {
+ case IMAGING_TYPE_UINT8:
+ return PyInt_FromLong(p[0]);
+ case IMAGING_TYPE_SPECIAL:
+ /* FIXME: are 16-bit images signed or unsigned??? */
+ if (strcmp(im->mode, "I;16") == 0) {
+ p = (UINT8*) &im->image8[y][x+x];
+ return PyInt_FromLong(L16(p, 0));
+ }
+ if (strcmp(im->mode, "I;16B") == 0) {
+ p = (UINT8*) &im->image8[y][x+x];
+ return PyInt_FromLong(B16(p, 0));
+ }
+ }
+ }
+
+ /* multilayer */
+ if (im->image32 != NULL) {
+ p = (UINT8*) &im->image32[y][x];
+ switch (im->type) {
+ case IMAGING_TYPE_UINT8:
+ /* unsigned integer */
+ if (im->bands == 2)
+ return Py_BuildValue("ii", p[0], p[3]);
+ if (im->bands == 3)
+ return Py_BuildValue("iii", p[0], p[1], p[2]);
+ return Py_BuildValue("iiii", p[0], p[1], p[2], p[3]);
+ case IMAGING_TYPE_INT32:
+ /* signed integer */
+ return PyInt_FromLong(*(INT32*) p);
+ case IMAGING_TYPE_FLOAT32:
+ /* floating point */
+ return PyFloat_FromDouble(*(FLOAT32*) p);
+ }
+ }
+
+ /* unknown type */
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char*
+getink(PyObject* color, Imaging im, char* ink)
+{
+ int r, g, b, a;
+ double f;
+
+ /* fill ink buffer (four bytes) with something that can
+ be cast to either UINT8 or INT32 */
+
+ if (im->image8) {
+ /* unsigned integer, single layer */
+ r = PyInt_AsLong(color);
+ if (r == -1 && PyErr_Occurred())
+ return NULL;
+ ink[0] = CLIP(r);
+ ink[1] = ink[2] = ink[3] = 0;
+ return ink;
+ } else {
+ switch (im->type) {
+ case IMAGING_TYPE_UINT8:
+ /* unsigned integer */
+ a = 255;
+ if (PyInt_Check(color)) {
+ r = PyInt_AS_LONG(color);
+ /* compatibility: ABGR */
+ a = (UINT8) (r >> 24);
+ b = (UINT8) (r >> 16);
+ g = (UINT8) (r >> 8);
+ r = (UINT8) r;
+ } else {
+ if (im->bands == 2) {
+ if (!PyArg_ParseTuple(color, "i|i", &r, &a))
+ return NULL;
+ g = b = r;
+ } else {
+ if (!PyArg_ParseTuple(color, "iii|i", &r, &g, &b, &a))
+ return NULL;
+ }
+ }
+ ink[0] = CLIP(r);
+ ink[1] = CLIP(g);
+ ink[2] = CLIP(b);
+ ink[3] = CLIP(a);
+ return ink;
+ case IMAGING_TYPE_INT32:
+ /* signed integer */
+ r = PyInt_AsLong(color);
+ if (r == -1 && PyErr_Occurred())
+ return NULL;
+ *(INT32*) ink = r;
+ return ink;
+ case IMAGING_TYPE_FLOAT32:
+ /* floating point */
+ f = PyFloat_AsDouble(color);
+ if (f == -1.0 && PyErr_Occurred())
+ return NULL;
+ *(FLOAT32*) ink = (FLOAT32) f;
+ return ink;
+ }
+ }
+
+ PyErr_SetString(PyExc_ValueError, wrong_mode);
+ return NULL;
+}
+
+/* -------------------------------------------------------------------- */
+/* FACTORIES */
+/* -------------------------------------------------------------------- */
+
+static PyObject*
+_fill(PyObject* self, PyObject* args)
+{
+ char* mode;
+ int xsize, ysize;
+ PyObject* color;
+ char buffer[4];
+ Imaging im;
+
+ xsize = ysize = 256;
+ color = NULL;
+
+ if (!PyArg_ParseTuple(args, "s|(ii)O", &mode, &xsize, &ysize, &color))
+ return NULL;
+
+ im = ImagingNew(mode, xsize, ysize);
+ if (!im)
+ return NULL;
+
+ if (color) {
+ if (!getink(color, im, buffer)) {
+ ImagingDelete(im);
+ return NULL;
+ }
+ } else
+ buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0;
+
+ ImagingFill(im, buffer);
+
+ return PyImagingNew(im);
+}
+
+static PyObject*
+_new(PyObject* self, PyObject* args)
+{
+ char* mode;
+ int xsize, ysize;
+
+ if (!PyArg_ParseTuple(args, "s(ii)", &mode, &xsize, &ysize))
+ return NULL;
+
+ return PyImagingNew(ImagingNew(mode, xsize, ysize));
+}
+
+static PyObject*
+_new_array(PyObject* self, PyObject* args)
+{
+ char* mode;
+ int xsize, ysize;
+
+ if (!PyArg_ParseTuple(args, "s(ii)", &mode, &xsize, &ysize))
+ return NULL;
+
+ return PyImagingNew(ImagingNewArray(mode, xsize, ysize));
+}
+
+static PyObject*
+_new_block(PyObject* self, PyObject* args)
+{
+ char* mode;
+ int xsize, ysize;
+
+ if (!PyArg_ParseTuple(args, "s(ii)", &mode, &xsize, &ysize))
+ return NULL;
+
+ return PyImagingNew(ImagingNewBlock(mode, xsize, ysize));
+}
+
+static PyObject*
+_getcount(PyObject* self, PyObject* args)
+{
+ if (!PyArg_ParseTuple(args, ":getcount"))
+ return NULL;
+
+ return PyInt_FromLong(ImagingNewCount);
+}
+
+static PyObject*
+_linear_gradient(PyObject* self, PyObject* args)
+{
+ char* mode;
+
+ if (!PyArg_ParseTuple(args, "s", &mode))
+ return NULL;
+
+ return PyImagingNew(ImagingFillLinearGradient(mode));
+}
+
+static PyObject*
+_radial_gradient(PyObject* self, PyObject* args)
+{
+ char* mode;
+
+ if (!PyArg_ParseTuple(args, "s", &mode))
+ return NULL;
+
+ return PyImagingNew(ImagingFillRadialGradient(mode));
+}
+
+static PyObject*
+_open_ppm(PyObject* self, PyObject* args)
+{
+ char* filename;
+
+ if (!PyArg_ParseTuple(args, "s", &filename))
+ return NULL;
+
+ return PyImagingNew(ImagingOpenPPM(filename));
+}
+
+static PyObject*
+_blend(ImagingObject* self, PyObject* args)
+{
+ ImagingObject* imagep1;
+ ImagingObject* imagep2;
+ double alpha;
+
+ alpha = 0.5;
+ if (!PyArg_ParseTuple(args, "O!O!|d",
+ &Imaging_Type, &imagep1,
+ &Imaging_Type, &imagep2,
+ &alpha))
+ return NULL;
+
+ return PyImagingNew(ImagingBlend(imagep1->image, imagep2->image,
+ (float) alpha));
+}
+
+/* -------------------------------------------------------------------- */
+/* METHODS */
+/* -------------------------------------------------------------------- */
+
+static PyObject*
+_convert(ImagingObject* self, PyObject* args)
+{
+ char* mode;
+ int dither = 0;
+ ImagingObject *paletteimage = NULL;
+
+ if (!PyArg_ParseTuple(args, "s|iO", &mode, &dither, &paletteimage))
+ return NULL;
+ if (paletteimage != NULL) {
+ if (!PyImaging_Check(paletteimage)) {
+ PyObject_Print((PyObject *)paletteimage, stderr, 0);
+ PyErr_SetString(PyExc_ValueError, "palette argument must be image with mode 'P'");
+ return NULL;
+ }
+ if (paletteimage->image->palette == NULL) {
+ PyErr_SetString(PyExc_ValueError, "null palette");
+ return NULL;
+ }
+ }
+
+ return PyImagingNew(ImagingConvert(self->image, mode, paletteimage ? paletteimage->image->palette : NULL, dither));
+}
+
+static PyObject*
+_convert2(ImagingObject* self, PyObject* args)
+{
+ ImagingObject* imagep1;
+ ImagingObject* imagep2;
+ if (!PyArg_ParseTuple(args, "O!O!",
+ &Imaging_Type, &imagep1,
+ &Imaging_Type, &imagep2))
+ return NULL;
+
+ if (!ImagingConvert2(imagep1->image, imagep2->image))
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_convert_matrix(ImagingObject* self, PyObject* args)
+{
+ char* mode;
+ float m[12];
+ if (!PyArg_ParseTuple(args, "s(ffff)", &mode, m+0, m+1, m+2, m+3)) {
+ PyErr_Clear();
+ if (!PyArg_ParseTuple(args, "s(ffffffffffff)", &mode,
+ m+0, m+1, m+2, m+3,
+ m+4, m+5, m+6, m+7,
+ m+8, m+9, m+10, m+11))
+ return NULL;
+ }
+
+ return PyImagingNew(ImagingConvertMatrix(self->image, mode, m));
+}
+
+static PyObject*
+_copy(ImagingObject* self, PyObject* args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ return PyImagingNew(ImagingCopy(self->image));
+}
+
+static PyObject*
+_copy2(ImagingObject* self, PyObject* args)
+{
+ ImagingObject* imagep1;
+ ImagingObject* imagep2;
+ if (!PyArg_ParseTuple(args, "O!O!",
+ &Imaging_Type, &imagep1,
+ &Imaging_Type, &imagep2))
+ return NULL;
+
+ if (!ImagingCopy2(imagep1->image, imagep2->image))
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_crop(ImagingObject* self, PyObject* args)
+{
+ int x0, y0, x1, y1;
+ if (!PyArg_ParseTuple(args, "(iiii)", &x0, &y0, &x1, &y1))
+ return NULL;
+
+ return PyImagingNew(ImagingCrop(self->image, x0, y0, x1, y1));
+}
+
+static PyObject*
+_expand(ImagingObject* self, PyObject* args)
+{
+ int x, y;
+ int mode = 0;
+ if (!PyArg_ParseTuple(args, "ii|i", &x, &y, &mode))
+ return NULL;
+
+ return PyImagingNew(ImagingExpand(self->image, x, y, mode));
+}
+
+static PyObject*
+_filter(ImagingObject* self, PyObject* args)
+{
+ PyObject* imOut;
+ int kernelsize;
+ FLOAT32* kerneldata;
+
+ int xsize, ysize;
+ float divisor, offset;
+ PyObject* kernel = NULL;
+ if (!PyArg_ParseTuple(args, "(ii)ffO", &xsize, &ysize,
+ &divisor, &offset, &kernel))
+ return NULL;
+
+ /* get user-defined kernel */
+ kerneldata = getlist(kernel, &kernelsize, NULL, TYPE_FLOAT32);
+ if (!kerneldata)
+ return NULL;
+ if (kernelsize != xsize * ysize) {
+ free(kerneldata);
+ return ImagingError_ValueError("bad kernel size");
+ }
+
+ imOut = PyImagingNew(
+ ImagingFilter(self->image, xsize, ysize, kerneldata, offset, divisor)
+ );
+
+ free(kerneldata);
+
+ return imOut;
+}
+
+static PyObject*
+_getpalette(ImagingObject* self, PyObject* args)
+{
+ PyObject* palette;
+ int palettesize = 256;
+ int bits;
+ ImagingShuffler pack;
+
+ char* mode = "RGB";
+ char* rawmode = "RGB";
+ if (!PyArg_ParseTuple(args, "|ss", &mode, &rawmode))
+ return NULL;
+
+ if (!self->image->palette) {
+ PyErr_SetString(PyExc_ValueError, no_palette);
+ return NULL;
+ }
+
+ pack = ImagingFindPacker(mode, rawmode, &bits);
+ if (!pack) {
+ PyErr_SetString(PyExc_ValueError, wrong_raw_mode);
+ return NULL;
+ }
+
+ palette = PyString_FromStringAndSize(NULL, palettesize * bits / 8);
+ if (!palette)
+ return NULL;
+
+ pack((UINT8*) PyString_AsString(palette),
+ self->image->palette->palette, palettesize);
+
+ return palette;
+}
+
+static inline int
+_getxy(PyObject* xy, int* x, int *y)
+{
+ PyObject* value;
+
+ if (!PyTuple_Check(xy) || PyTuple_GET_SIZE(xy) != 2)
+ goto badarg;
+
+ value = PyTuple_GET_ITEM(xy, 0);
+ if (PyInt_Check(value))
+ *x = PyInt_AS_LONG(value);
+ else if (PyFloat_Check(value))
+ *x = (int) PyFloat_AS_DOUBLE(value);
+ else
+ goto badval;
+
+ value = PyTuple_GET_ITEM(xy, 1);
+ if (PyInt_Check(value))
+ *y = PyInt_AS_LONG(value);
+ else if (PyFloat_Check(value))
+ *y = (int) PyFloat_AS_DOUBLE(value);
+ else
+ goto badval;
+
+ return 0;
+
+ badarg:
+ PyErr_SetString(
+ PyExc_TypeError,
+ "argument must be sequence of length 2"
+ );
+ return -1;
+
+ badval:
+ PyErr_SetString(
+ PyExc_TypeError,
+ "an integer is required"
+ );
+ return -1;
+}
+
+static PyObject*
+_getpixel(ImagingObject* self, PyObject* args)
+{
+ PyObject* xy;
+ int x, y;
+
+ if (PyTuple_GET_SIZE(args) != 1) {
+ PyErr_SetString(
+ PyExc_TypeError,
+ "argument 1 must be sequence of length 2"
+ );
+ return NULL;
+ }
+
+ xy = PyTuple_GET_ITEM(args, 0);
+
+ if (_getxy(xy, &x, &y))
+ return NULL;
+
+ return getpixel(self->image, x, y);
+}
+
+static PyObject*
+_histogram(ImagingObject* self, PyObject* args)
+{
+ ImagingHistogram h;
+ PyObject* list;
+ int i;
+ union {
+ UINT8 u[2];
+ INT32 i[2];
+ FLOAT32 f[2];
+ } extrema;
+ void* ep;
+ int i0, i1;
+ double f0, f1;
+
+ PyObject* extremap = NULL;
+ ImagingObject* maskp = NULL;
+ if (!PyArg_ParseTuple(args, "|OO!", &extremap, &Imaging_Type, &maskp))
+ return NULL;
+
+ if (extremap) {
+ ep = &extrema;
+ switch (self->image->type) {
+ case IMAGING_TYPE_UINT8:
+ if (!PyArg_ParseTuple(extremap, "ii", &i0, &i1))
+ return NULL;
+ /* FIXME: clip */
+ extrema.u[0] = i0;
+ extrema.u[1] = i1;
+ break;
+ case IMAGING_TYPE_INT32:
+ if (!PyArg_ParseTuple(extremap, "ii", &i0, &i1))
+ return NULL;
+ extrema.i[0] = i0;
+ extrema.i[1] = i1;
+ break;
+ case IMAGING_TYPE_FLOAT32:
+ if (!PyArg_ParseTuple(extremap, "dd", &f0, &f1))
+ return NULL;
+ extrema.f[0] = (FLOAT32) f0;
+ extrema.f[1] = (FLOAT32) f1;
+ break;
+ default:
+ ep = NULL;
+ break;
+ }
+ } else
+ ep = NULL;
+
+ h = ImagingGetHistogram(self->image, (maskp) ? maskp->image : NULL, ep);
+
+ if (!h)
+ return NULL;
+
+ /* Build an integer list containing the histogram */
+ list = PyList_New(h->bands * 256);
+ for (i = 0; i < h->bands * 256; i++) {
+ PyObject* item;
+ item = PyInt_FromLong(h->histogram[i]);
+ if (item == NULL) {
+ Py_DECREF(list);
+ list = NULL;
+ break;
+ }
+ PyList_SetItem(list, i, item);
+ }
+
+ ImagingHistogramDelete(h);
+
+ return list;
+}
+
+#ifdef WITH_MODEFILTER
+static PyObject*
+_modefilter(ImagingObject* self, PyObject* args)
+{
+ int size;
+ if (!PyArg_ParseTuple(args, "i", &size))
+ return NULL;
+
+ return PyImagingNew(ImagingModeFilter(self->image, size));
+}
+#endif
+
+static PyObject*
+_offset(ImagingObject* self, PyObject* args)
+{
+ int xoffset, yoffset;
+ if (!PyArg_ParseTuple(args, "ii", &xoffset, &yoffset))
+ return NULL;
+
+ return PyImagingNew(ImagingOffset(self->image, xoffset, yoffset));
+}
+
+static PyObject*
+_paste(ImagingObject* self, PyObject* args)
+{
+ int status;
+ char ink[4];
+
+ PyObject* source;
+ int x0, y0, x1, y1;
+ ImagingObject* maskp = NULL;
+ if (!PyArg_ParseTuple(args, "O(iiii)|O!",
+ &source,
+ &x0, &y0, &x1, &y1,
+ &Imaging_Type, &maskp))
+ return NULL;
+
+ if (PyImaging_Check(source))
+ status = ImagingPaste(
+ self->image, PyImaging_AsImaging(source),
+ (maskp) ? maskp->image : NULL,
+ x0, y0, x1, y1
+ );
+
+ else {
+ if (!getink(source, self->image, ink))
+ return NULL;
+ status = ImagingFill2(
+ self->image, ink,
+ (maskp) ? maskp->image : NULL,
+ x0, y0, x1, y1
+ );
+ }
+
+ if (status < 0)
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_point(ImagingObject* self, PyObject* args)
+{
+ static const char* wrong_number = "wrong number of lut entries";
+
+ int n, i;
+ int bands;
+ Imaging im;
+
+ PyObject* list;
+ char* mode;
+ if (!PyArg_ParseTuple(args, "Oz", &list, &mode))
+ return NULL;
+
+ if (mode && !strcmp(mode, "F")) {
+ FLOAT32* data;
+
+ /* map from 8-bit data to floating point */
+ n = 256;
+ data = getlist(list, &n, wrong_number, TYPE_FLOAT32);
+ if (!data)
+ return NULL;
+ im = ImagingPoint(self->image, mode, (void*) data);
+ free(data);
+
+ } else if (!strcmp(self->image->mode, "I") && mode && !strcmp(mode, "L")) {
+ UINT8* data;
+
+ /* map from 16-bit subset of 32-bit data to 8-bit */
+ /* FIXME: support arbitrary number of entries (requires API change) */
+ n = 65536;
+ data = getlist(list, &n, wrong_number, TYPE_UINT8);
+ if (!data)
+ return NULL;
+ im = ImagingPoint(self->image, mode, (void*) data);
+ free(data);
+
+ } else {
+ INT32* data;
+ UINT8 lut[1024];
+
+ if (mode) {
+ bands = getbands(mode);
+ if (bands < 0)
+ return NULL;
+ } else
+ bands = self->image->bands;
+
+ /* map to integer data */
+ n = 256 * bands;
+ data = getlist(list, &n, wrong_number, TYPE_INT32);
+ if (!data)
+ return NULL;
+
+ if (mode && !strcmp(mode, "I"))
+ im = ImagingPoint(self->image, mode, (void*) data);
+ else if (mode && bands > 1) {
+ for (i = 0; i < 256; i++) {
+ lut[i*4] = CLIP(data[i]);
+ lut[i*4+1] = CLIP(data[i+256]);
+ lut[i*4+2] = CLIP(data[i+512]);
+ if (n > 768)
+ lut[i*4+3] = CLIP(data[i+768]);
+ }
+ im = ImagingPoint(self->image, mode, (void*) lut);
+ } else {
+ /* map individual bands */
+ for (i = 0; i < n; i++)
+ lut[i] = CLIP(data[i]);
+ im = ImagingPoint(self->image, mode, (void*) lut);
+ }
+ free(data);
+ }
+
+ return PyImagingNew(im);
+}
+
+static PyObject*
+_point_transform(ImagingObject* self, PyObject* args)
+{
+ double scale = 1.0;
+ double offset = 0.0;
+ if (!PyArg_ParseTuple(args, "|dd", &scale, &offset))
+ return NULL;
+
+ return PyImagingNew(ImagingPointTransform(self->image, scale, offset));
+}
+
+static PyObject*
+_putdata(ImagingObject* self, PyObject* args)
+{
+ Imaging image;
+ int n, i, x, y;
+
+ PyObject* data;
+ double scale = 1.0;
+ double offset = 0.0;
+ if (!PyArg_ParseTuple(args, "O|dd", &data, &scale, &offset))
+ return NULL;
+
+ if (!PySequence_Check(data)) {
+ PyErr_SetString(PyExc_TypeError, must_be_sequence);
+ return NULL;
+ }
+
+ image = self->image;
+
+ n = PyObject_Length(data);
+ if (n > (int) (image->xsize * image->ysize)) {
+ PyErr_SetString(PyExc_TypeError, "too many data entries");
+ return NULL;
+ }
+
+ if (image->image8) {
+ if (PyString_Check(data)) {
+ unsigned char* p;
+ p = (unsigned char*) PyString_AS_STRING((PyStringObject*) data);
+ if (scale == 1.0 && offset == 0.0)
+ /* Plain string data */
+ for (i = y = 0; i < n; i += image->xsize, y++) {
+ x = n - i;
+ if (x > (int) image->xsize)
+ x = image->xsize;
+ memcpy(image->image8[y], p+i, x);
+ }
+ else
+ /* Scaled and clipped string data */
+ for (i = x = y = 0; i < n; i++) {
+ image->image8[y][x] = CLIP((int) (p[i] * scale + offset));
+ if (++x >= (int) image->xsize)
+ x = 0, y++;
+ }
+ } else {
+ if (scale == 1.0 && offset == 0.0) {
+ /* Clipped data */
+ if (PyList_Check(data)) {
+ for (i = x = y = 0; i < n; i++) {
+ PyObject *op = PyList_GET_ITEM(data, i);
+ image->image8[y][x] = CLIP(PyInt_AsLong(op));
+ if (++x >= (int) image->xsize)
+ x = 0, y++;
+ }
+ } else {
+ for (i = x = y = 0; i < n; i++) {
+ PyObject *op = PySequence_GetItem(data, i);
+ image->image8[y][x] = CLIP(PyInt_AsLong(op));
+ Py_XDECREF(op);
+ if (++x >= (int) image->xsize)
+ x = 0, y++;
+ }
+ }
+ } else {
+ if (PyList_Check(data)) {
+ /* Scaled and clipped data */
+ for (i = x = y = 0; i < n; i++) {
+ PyObject *op = PyList_GET_ITEM(data, i);
+ image->image8[y][x] = CLIP(
+ (int) (PyFloat_AsDouble(op) * scale + offset));
+ if (++x >= (int) image->xsize)
+ x = 0, y++;
+ }
+ } else {
+ for (i = x = y = 0; i < n; i++) {
+ PyObject *op = PySequence_GetItem(data, i);
+ image->image8[y][x] = CLIP(
+ (int) (PyFloat_AsDouble(op) * scale + offset));
+ Py_XDECREF(op);
+ if (++x >= (int) image->xsize)
+ x = 0, y++;
+ }
+ }
+ }
+ PyErr_Clear(); /* Avoid weird exceptions */
+ }
+ } else {
+ /* 32-bit images */
+ switch (image->type) {
+ case IMAGING_TYPE_INT32:
+ for (i = x = y = 0; i < n; i++) {
+ PyObject *op = PySequence_GetItem(data, i);
+ IMAGING_PIXEL_INT32(image, x, y) =
+ (INT32) (PyFloat_AsDouble(op) * scale + offset);
+ Py_XDECREF(op);
+ if (++x >= (int) image->xsize)
+ x = 0, y++;
+ }
+ PyErr_Clear(); /* Avoid weird exceptions */
+ break;
+ case IMAGING_TYPE_FLOAT32:
+ for (i = x = y = 0; i < n; i++) {
+ PyObject *op = PySequence_GetItem(data, i);
+ IMAGING_PIXEL_FLOAT32(image, x, y) =
+ (FLOAT32) (PyFloat_AsDouble(op) * scale + offset);
+ Py_XDECREF(op);
+ if (++x >= (int) image->xsize)
+ x = 0, y++;
+ }
+ PyErr_Clear(); /* Avoid weird exceptions */
+ break;
+ default:
+ for (i = x = y = 0; i < n; i++) {
+ char ink[4];
+ PyObject *op = PySequence_GetItem(data, i);
+ if (!op || !getink(op, image, ink)) {
+ Py_DECREF(op);
+ return NULL;
+ }
+ /* FIXME: what about scale and offset? */
+ image->image32[y][x] = *((INT32*) ink);
+ Py_XDECREF(op);
+ if (++x >= (int) image->xsize)
+ x = 0, y++;
+ }
+ PyErr_Clear(); /* Avoid weird exceptions */
+ break;
+ }
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+#ifdef WITH_QUANTIZE
+
+#include "Quant.h"
+static PyObject*
+_quantize(ImagingObject* self, PyObject* args)
+{
+ int colours = 256;
+ int method = 0;
+ int kmeans = 0;
+ if (!PyArg_ParseTuple(args, "|iii", &colours, &method, &kmeans))
+ return NULL;
+
+ if (!self->image->xsize || !self->image->ysize) {
+ /* no content; return an empty image */
+ return PyImagingNew(
+ ImagingNew("P", self->image->xsize, self->image->ysize)
+ );
+ }
+
+ return PyImagingNew(ImagingQuantize(self->image, colours, method, kmeans));
+}
+#endif
+
+static PyObject*
+_putpalette(ImagingObject* self, PyObject* args)
+{
+ ImagingShuffler unpack;
+ int bits;
+
+ char* rawmode;
+ UINT8* palette;
+ int palettesize;
+ if (!PyArg_ParseTuple(args, "ss#", &rawmode, &palette, &palettesize))
+ return NULL;
+
+ if (strcmp(self->image->mode, "L") != 0 && strcmp(self->image->mode, "P")) {
+ PyErr_SetString(PyExc_ValueError, wrong_mode);
+ return NULL;
+ }
+
+ unpack = ImagingFindUnpacker("RGB", rawmode, &bits);
+ if (!unpack) {
+ PyErr_SetString(PyExc_ValueError, wrong_raw_mode);
+ return NULL;
+ }
+
+ ImagingPaletteDelete(self->image->palette);
+
+ strcpy(self->image->mode, "P");
+
+ self->image->palette = ImagingPaletteNew("RGB");
+
+ unpack(self->image->palette->palette, palette, palettesize * 8 / bits);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_putpalettealpha(ImagingObject* self, PyObject* args)
+{
+ int index;
+ int alpha = 0;
+ if (!PyArg_ParseTuple(args, "i|i", &index, &alpha))
+ return NULL;
+
+ if (!self->image->palette) {
+ PyErr_SetString(PyExc_ValueError, no_palette);
+ return NULL;
+ }
+
+ if (index < 0 || index >= 256) {
+ PyErr_SetString(PyExc_ValueError, outside_palette);
+ return NULL;
+ }
+
+ strcpy(self->image->palette->mode, "RGBA");
+ self->image->palette->palette[index*4+3] = (UINT8) alpha;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_putpixel(ImagingObject* self, PyObject* args)
+{
+ Imaging im;
+ char ink[4];
+
+ int x, y;
+ PyObject* color;
+ if (!PyArg_ParseTuple(args, "(ii)O", &x, &y, &color))
+ return NULL;
+
+ im = self->image;
+
+ if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) {
+ PyErr_SetString(PyExc_IndexError, outside_image);
+ return NULL;
+ }
+
+ if (!getink(color, im, ink))
+ return NULL;
+
+ if (im->image8)
+ im->image8[y][x] = ink[0];
+ else
+ im->image32[y][x] = *((INT32*) ink);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+#ifdef WITH_RANKFILTER
+static PyObject*
+_rankfilter(ImagingObject* self, PyObject* args)
+{
+ int size, rank;
+ if (!PyArg_ParseTuple(args, "ii", &size, &rank))
+ return NULL;
+
+ return PyImagingNew(ImagingRankFilter(self->image, size, rank));
+}
+#endif
+
+static PyObject*
+_resize(ImagingObject* self, PyObject* args)
+{
+ Imaging imIn;
+ Imaging imOut;
+
+ int xsize, ysize;
+ int filter = IMAGING_TRANSFORM_NEAREST;
+ if (!PyArg_ParseTuple(args, "(ii)|i", &xsize, &ysize, &filter))
+ return NULL;
+
+ imIn = self->image;
+
+ imOut = ImagingNew(imIn->mode, xsize, ysize);
+ if (imOut)
+ ImagingResize(imOut, imIn, filter);
+
+ return PyImagingNew(imOut);
+}
+
+static PyObject*
+_rotate(ImagingObject* self, PyObject* args)
+{
+ Imaging imOut;
+ Imaging imIn;
+
+ double theta;
+ int filter = IMAGING_TRANSFORM_NEAREST;
+ if (!PyArg_ParseTuple(args, "d|i", &theta, &filter))
+ return NULL;
+
+ imIn = self->image;
+
+ theta = fmod(theta, 360.0);
+ if (theta < 0.0)
+ theta += 360;
+
+ if (filter && imIn->type != IMAGING_TYPE_SPECIAL) {
+ /* Rotate with resampling filter */
+ imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize);
+ ImagingRotate(imOut, imIn, theta, filter);
+ } else if (theta == 90.0 || theta == 270.0) {
+ /* Use fast version */
+ imOut = ImagingNew(imIn->mode, imIn->ysize, imIn->xsize);
+ if (imOut) {
+ if (theta == 90.0)
+ ImagingRotate90(imOut, imIn);
+ else
+ ImagingRotate270(imOut, imIn);
+ }
+ } else {
+ imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize);
+ if (imOut) {
+ if (theta == 0.0)
+ /* No rotation: simply copy the input image */
+ ImagingCopy2(imOut, imIn);
+ else if (theta == 180.0)
+ /* Use fast version */
+ ImagingRotate180(imOut, imIn);
+ else
+ /* Use ordinary version */
+ ImagingRotate(imOut, imIn, theta, 0);
+ }
+ }
+
+ return PyImagingNew(imOut);
+}
+
+#define IS_RGB(mode)\
+ (!strcmp(mode, "RGB") || !strcmp(mode, "RGBA") || !strcmp(mode, "RGBX"))
+
+static PyObject*
+im_setmode(ImagingObject* self, PyObject* args)
+{
+ /* attempt to modify the mode of an image in place */
+
+ Imaging im;
+
+ char* mode;
+ int modelen;
+ if (!PyArg_ParseTuple(args, "s#:setmode", &mode, &modelen))
+ return NULL;
+
+ im = self->image;
+
+ /* FIXME: move this to a libImaging primitive (?) */
+ /* FIXME: add support for 1->L and L->1 */
+
+ if (!strcmp(im->mode, mode)) {
+ ; /* same mode; always succeeds */
+ } else if (IS_RGB(im->mode) && IS_RGB(mode)) {
+ /* color to color */
+ strcpy(im->mode, mode);
+ im->bands = modelen;
+ if (!strcmp(mode, "RGBA"))
+ ImagingFillBand(im, 3, 255);
+ } else
+ return ImagingError_ModeError();
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_stretch(ImagingObject* self, PyObject* args)
+{
+ Imaging imIn;
+ Imaging imTemp;
+ Imaging imOut;
+
+ int xsize, ysize;
+ int filter = IMAGING_TRANSFORM_NEAREST;
+ if (!PyArg_ParseTuple(args, "(ii)|i", &xsize, &ysize, &filter))
+ return NULL;
+
+ imIn = self->image;
+
+ /* two-pass resize: minimize size of intermediate image */
+ if (imIn->xsize * ysize < xsize * imIn->ysize)
+ imTemp = ImagingNew(imIn->mode, imIn->xsize, ysize);
+ else
+ imTemp = ImagingNew(imIn->mode, xsize, imIn->ysize);
+ if (!imTemp)
+ return NULL;
+
+ /* first pass */
+ if (!ImagingStretch(imTemp, imIn, filter)) {
+ ImagingDelete(imTemp);
+ return NULL;
+ }
+
+ imOut = ImagingNew(imIn->mode, xsize, ysize);
+ if (!imOut) {
+ ImagingDelete(imTemp);
+ return NULL;
+ }
+
+ /* second pass */
+ if (!ImagingStretch(imOut, imTemp, filter)) {
+ ImagingDelete(imOut);
+ ImagingDelete(imTemp);
+ return NULL;
+ }
+
+ ImagingDelete(imTemp);
+
+ return PyImagingNew(imOut);
+}
+
+static PyObject*
+_transform2(ImagingObject* self, PyObject* args)
+{
+ static const char* wrong_number = "wrong number of matrix entries";
+
+ Imaging imIn;
+ Imaging imOut;
+ int n;
+ double *a;
+
+ ImagingObject* imagep;
+ int x0, y0, x1, y1;
+ int method;
+ PyObject* data;
+ int filter = IMAGING_TRANSFORM_NEAREST;
+ int fill = 1;
+ if (!PyArg_ParseTuple(args, "(iiii)O!iO|ii",
+ &x0, &y0, &x1, &y1,
+ &Imaging_Type, &imagep,
+ &method, &data,
+ &filter, &fill))
+ return NULL;
+
+ switch (method) {
+ case IMAGING_TRANSFORM_AFFINE:
+ n = 6;
+ break;
+ case IMAGING_TRANSFORM_PERSPECTIVE:
+ n = 8;
+ break;
+ case IMAGING_TRANSFORM_QUAD:
+ n = 8;
+ break;
+ default:
+ n = -1; /* force error */
+ }
+
+ a = getlist(data, &n, wrong_number, TYPE_DOUBLE);
+ if (!a)
+ return NULL;
+
+ imOut = self->image;
+ imIn = imagep->image;
+
+ /* FIXME: move transform dispatcher into libImaging */
+
+ switch (method) {
+ case IMAGING_TRANSFORM_AFFINE:
+ imOut = ImagingTransformAffine(
+ imOut, imIn, x0, y0, x1, y1, a, filter, 1
+ );
+ break;
+ case IMAGING_TRANSFORM_PERSPECTIVE:
+ imOut = ImagingTransformPerspective(
+ imOut, imIn, x0, y0, x1, y1, a, filter, 1
+ );
+ break;
+ case IMAGING_TRANSFORM_QUAD:
+ imOut = ImagingTransformQuad(
+ imOut, imIn, x0, y0, x1, y1, a, filter, 1
+ );
+ break;
+ default:
+ ImagingError_ValueError("bad transform method");
+ }
+
+ free(a);
+
+ if (!imOut)
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_transpose(ImagingObject* self, PyObject* args)
+{
+ Imaging imIn;
+ Imaging imOut;
+
+ int op;
+ if (!PyArg_ParseTuple(args, "i", &op))
+ return NULL;
+
+ imIn = self->image;
+
+ switch (op) {
+ case 0: /* flip left right */
+ case 1: /* flip top bottom */
+ case 3: /* rotate 180 */
+ imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize);
+ break;
+ case 2: /* rotate 90 */
+ case 4: /* rotate 270 */
+ imOut = ImagingNew(imIn->mode, imIn->ysize, imIn->xsize);
+ break;
+ default:
+ PyErr_SetString(PyExc_ValueError, "No such transpose operation");
+ return NULL;
+ }
+
+ if (imOut)
+ switch (op) {
+ case 0:
+ ImagingFlipLeftRight(imOut, imIn);
+ break;
+ case 1:
+ ImagingFlipTopBottom(imOut, imIn);
+ break;
+ case 2:
+ ImagingRotate90(imOut, imIn);
+ break;
+ case 3:
+ ImagingRotate180(imOut, imIn);
+ break;
+ case 4:
+ ImagingRotate270(imOut, imIn);
+ break;
+ }
+
+ return PyImagingNew(imOut);
+}
+
+/* -------------------------------------------------------------------- */
+
+static PyObject*
+_isblock(ImagingObject* self, PyObject* args)
+{
+ return PyInt_FromLong((long) self->image->block);
+}
+
+static PyObject*
+_getbbox(ImagingObject* self, PyObject* args)
+{
+ int bbox[4];
+ if (!ImagingGetBBox(self->image, bbox)) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return Py_BuildValue("iiii", bbox[0], bbox[1], bbox[2], bbox[3]);
+}
+
+static PyObject*
+_getcolors(ImagingObject* self, PyObject* args)
+{
+ ImagingColorItem* items;
+ int i, colors;
+ PyObject* out;
+
+ int maxcolors = 256;
+ if (!PyArg_ParseTuple(args, "i:getcolors", &maxcolors))
+ return NULL;
+
+ items = ImagingGetColors(self->image, maxcolors, &colors);
+ if (!items)
+ return NULL;
+
+ if (colors > maxcolors) {
+ out = Py_None;
+ Py_INCREF(out);
+ } else {
+ out = PyList_New(colors);
+ for (i = 0; i < colors; i++) {
+ ImagingColorItem* v = &items[i];
+ PyObject* item = Py_BuildValue(
+ "iN", v->count, getpixel(self->image, v->x, v->y)
+ );
+ PyList_SetItem(out, i, item);
+ }
+ }
+
+ free(items);
+
+ return out;
+}
+
+static PyObject*
+_getextrema(ImagingObject* self, PyObject* args)
+{
+ union {
+ UINT8 u[2];
+ INT32 i[2];
+ FLOAT32 f[2];
+ } extrema;
+ int status;
+
+ status = ImagingGetExtrema(self->image, &extrema);
+ if (status < 0)
+ return NULL;
+
+ if (status)
+ switch (self->image->type) {
+ case IMAGING_TYPE_UINT8:
+ return Py_BuildValue("ii", extrema.u[0], extrema.u[1]);
+ case IMAGING_TYPE_INT32:
+ return Py_BuildValue("ii", extrema.i[0], extrema.i[1]);
+ case IMAGING_TYPE_FLOAT32:
+ return Py_BuildValue("dd", extrema.f[0], extrema.f[1]);
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_getprojection(ImagingObject* self, PyObject* args)
+{
+ unsigned char* xprofile;
+ unsigned char* yprofile;
+ PyObject* result;
+
+ xprofile = malloc(self->image->xsize);
+ yprofile = malloc(self->image->ysize);
+
+ if (xprofile == NULL || yprofile == NULL) {
+ free(xprofile);
+ free(yprofile);
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ ImagingGetProjection(self->image, (unsigned char *)xprofile, (unsigned char *)yprofile);
+
+ result = Py_BuildValue("s#s#", xprofile, self->image->xsize,
+ yprofile, self->image->ysize);
+
+ free(xprofile);
+ free(yprofile);
+
+ return result;
+}
+
+/* -------------------------------------------------------------------- */
+
+static PyObject*
+_getband(ImagingObject* self, PyObject* args)
+{
+ int band;
+
+ if (!PyArg_ParseTuple(args, "i", &band))
+ return NULL;
+
+ return PyImagingNew(ImagingGetBand(self->image, band));
+}
+
+static PyObject*
+_fillband(ImagingObject* self, PyObject* args)
+{
+ int band;
+ int color;
+
+ if (!PyArg_ParseTuple(args, "ii", &band, &color))
+ return NULL;
+
+ if (!ImagingFillBand(self->image, band, color))
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_putband(ImagingObject* self, PyObject* args)
+{
+ ImagingObject* imagep;
+ int band;
+ if (!PyArg_ParseTuple(args, "O!i",
+ &Imaging_Type, &imagep,
+ &band))
+ return NULL;
+
+ if (!ImagingPutBand(self->image, imagep->image, band))
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/* -------------------------------------------------------------------- */
+
+#ifdef WITH_IMAGECHOPS
+
+static PyObject*
+_chop_invert(ImagingObject* self, PyObject* args)
+{
+ return PyImagingNew(ImagingNegative(self->image));
+}
+
+static PyObject*
+_chop_lighter(ImagingObject* self, PyObject* args)
+{
+ ImagingObject* imagep;
+
+ if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
+ return NULL;
+
+ return PyImagingNew(ImagingChopLighter(self->image, imagep->image));
+}
+
+static PyObject*
+_chop_darker(ImagingObject* self, PyObject* args)
+{
+ ImagingObject* imagep;
+
+ if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
+ return NULL;
+
+ return PyImagingNew(ImagingChopDarker(self->image, imagep->image));
+}
+
+static PyObject*
+_chop_difference(ImagingObject* self, PyObject* args)
+{
+ ImagingObject* imagep;
+
+ if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
+ return NULL;
+
+ return PyImagingNew(ImagingChopDifference(self->image, imagep->image));
+}
+
+static PyObject*
+_chop_multiply(ImagingObject* self, PyObject* args)
+{
+ ImagingObject* imagep;
+
+ if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
+ return NULL;
+
+ return PyImagingNew(ImagingChopMultiply(self->image, imagep->image));
+}
+
+static PyObject*
+_chop_screen(ImagingObject* self, PyObject* args)
+{
+ ImagingObject* imagep;
+
+ if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
+ return NULL;
+
+ return PyImagingNew(ImagingChopScreen(self->image, imagep->image));
+}
+
+static PyObject*
+_chop_add(ImagingObject* self, PyObject* args)
+{
+ ImagingObject* imagep;
+ float scale;
+ int offset;
+
+ scale = 1.0;
+ offset = 0;
+
+ if (!PyArg_ParseTuple(args, "O!|fi", &Imaging_Type, &imagep,
+ &scale, &offset))
+ return NULL;
+
+ return PyImagingNew(ImagingChopAdd(self->image, imagep->image,
+ scale, offset));
+}
+
+static PyObject*
+_chop_subtract(ImagingObject* self, PyObject* args)
+{
+ ImagingObject* imagep;
+ float scale;
+ int offset;
+
+ scale = 1.0;
+ offset = 0;
+
+ if (!PyArg_ParseTuple(args, "O!|fi", &Imaging_Type, &imagep,
+ &scale, &offset))
+ return NULL;
+
+ return PyImagingNew(ImagingChopSubtract(self->image, imagep->image,
+ scale, offset));
+}
+
+static PyObject*
+_chop_and(ImagingObject* self, PyObject* args)
+{
+ ImagingObject* imagep;
+
+ if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
+ return NULL;
+
+ return PyImagingNew(ImagingChopAnd(self->image, imagep->image));
+}
+
+static PyObject*
+_chop_or(ImagingObject* self, PyObject* args)
+{
+ ImagingObject* imagep;
+
+ if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
+ return NULL;
+
+ return PyImagingNew(ImagingChopOr(self->image, imagep->image));
+}
+
+static PyObject*
+_chop_xor(ImagingObject* self, PyObject* args)
+{
+ ImagingObject* imagep;
+
+ if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
+ return NULL;
+
+ return PyImagingNew(ImagingChopXor(self->image, imagep->image));
+}
+
+static PyObject*
+_chop_add_modulo(ImagingObject* self, PyObject* args)
+{
+ ImagingObject* imagep;
+
+ if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
+ return NULL;
+
+ return PyImagingNew(ImagingChopAddModulo(self->image, imagep->image));
+}
+
+static PyObject*
+_chop_subtract_modulo(ImagingObject* self, PyObject* args)
+{
+ ImagingObject* imagep;
+
+ if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
+ return NULL;
+
+ return PyImagingNew(ImagingChopSubtractModulo(self->image, imagep->image));
+}
+
+#endif
+
+
+/* -------------------------------------------------------------------- */
+
+#ifdef WITH_IMAGEDRAW
+
+static PyObject*
+_font_new(PyObject* self_, PyObject* args)
+{
+ ImagingFontObject *self;
+ int i, y0, y1;
+ static const char* wrong_length = "descriptor table has wrong size";
+
+ ImagingObject* imagep;
+ unsigned char* glyphdata;
+ int glyphdata_length;
+ if (!PyArg_ParseTuple(args, "O!s#",
+ &Imaging_Type, &imagep,
+ &glyphdata, &glyphdata_length))
+ return NULL;
+
+ if (glyphdata_length != 256 * 20) {
+ PyErr_SetString(PyExc_ValueError, wrong_length);
+ return NULL;
+ }
+
+ self = PyObject_New(ImagingFontObject, &ImagingFont_Type);
+ if (self == NULL)
+ return NULL;
+
+ /* glyph bitmap */
+ self->bitmap = imagep->image;
+
+ y0 = y1 = 0;
+
+ /* glyph glyphs */
+ for (i = 0; i < 256; i++) {
+ self->glyphs[i].dx = S16(B16(glyphdata, 0));
+ self->glyphs[i].dy = S16(B16(glyphdata, 2));
+ self->glyphs[i].dx0 = S16(B16(glyphdata, 4));
+ self->glyphs[i].dy0 = S16(B16(glyphdata, 6));
+ self->glyphs[i].dx1 = S16(B16(glyphdata, 8));
+ self->glyphs[i].dy1 = S16(B16(glyphdata, 10));
+ self->glyphs[i].sx0 = S16(B16(glyphdata, 12));
+ self->glyphs[i].sy0 = S16(B16(glyphdata, 14));
+ self->glyphs[i].sx1 = S16(B16(glyphdata, 16));
+ self->glyphs[i].sy1 = S16(B16(glyphdata, 18));
+ if (self->glyphs[i].dy0 < y0)
+ y0 = self->glyphs[i].dy0;
+ if (self->glyphs[i].dy1 > y1)
+ y1 = self->glyphs[i].dy1;
+ glyphdata += 20;
+ }
+
+ self->baseline = -y0;
+ self->ysize = y1 - y0;
+
+ /* keep a reference to the bitmap object */
+ Py_INCREF(imagep);
+ self->ref = imagep;
+
+ return (PyObject*) self;
+}
+
+static void
+_font_dealloc(ImagingFontObject* self)
+{
+ Py_XDECREF(self->ref);
+ PyObject_Del(self);
+}
+
+static inline int
+textwidth(ImagingFontObject* self, const unsigned char* text)
+{
+ int xsize;
+
+ for (xsize = 0; *text; text++)
+ xsize += self->glyphs[*text].dx;
+
+ return xsize;
+}
+
+static PyObject*
+_font_getmask(ImagingFontObject* self, PyObject* args)
+{
+ Imaging im;
+ Imaging bitmap;
+ int x, b;
+ int status;
+ Glyph* glyph;
+
+ unsigned char* text;
+ char* mode = "";
+ if (!PyArg_ParseTuple(args, "s|s:getmask", &text, &mode))
+ return NULL;
+
+ im = ImagingNew(self->bitmap->mode, textwidth(self, text), self->ysize);
+ if (!im)
+ return NULL;
+
+ b = 0;
+ ImagingFill(im, &b);
+
+ b = self->baseline;
+ for (x = 0; *text; text++) {
+ glyph = &self->glyphs[*text];
+ bitmap = ImagingCrop(
+ self->bitmap,
+ glyph->sx0, glyph->sy0, glyph->sx1, glyph->sy1
+ );
+ if (!bitmap)
+ goto failed;
+ status = ImagingPaste(
+ im, bitmap, NULL,
+ glyph->dx0+x, glyph->dy0+b, glyph->dx1+x, glyph->dy1+b
+ );
+ ImagingDelete(bitmap);
+ if (status < 0)
+ goto failed;
+ x = x + glyph->dx;
+ b = b + glyph->dy;
+ }
+
+ return PyImagingNew(im);
+
+ failed:
+ ImagingDelete(im);
+ return NULL;
+}
+
+static PyObject*
+_font_getsize(ImagingFontObject* self, PyObject* args)
+{
+ unsigned char* text;
+ if (!PyArg_ParseTuple(args, "s:getsize", &text))
+ return NULL;
+
+ return Py_BuildValue("ii", textwidth(self, text), self->ysize);
+}
+
+static struct PyMethodDef _font_methods[] = {
+ {"getmask", (PyCFunction)_font_getmask, 1},
+ {"getsize", (PyCFunction)_font_getsize, 1},
+ {NULL, NULL} /* sentinel */
+};
+
+static PyObject*
+_font_getattr(ImagingFontObject* self, char* name)
+{
+ return Py_FindMethod(_font_methods, (PyObject*) self, name);
+}
+
+/* -------------------------------------------------------------------- */
+
+static PyObject*
+_draw_new(PyObject* self_, PyObject* args)
+{
+ ImagingDrawObject *self;
+
+ ImagingObject* imagep;
+ int blend = 0;
+ if (!PyArg_ParseTuple(args, "O!|i", &Imaging_Type, &imagep, &blend))
+ return NULL;
+
+ self = PyObject_New(ImagingDrawObject, &ImagingDraw_Type);
+ if (self == NULL)
+ return NULL;
+
+ /* keep a reference to the image object */
+ Py_INCREF(imagep);
+ self->image = imagep;
+
+ self->ink[0] = self->ink[1] = self->ink[2] = self->ink[3] = 0;
+
+ self->blend = blend;
+
+ return (PyObject*) self;
+}
+
+static void
+_draw_dealloc(ImagingDrawObject* self)
+{
+ Py_XDECREF(self->image);
+ PyObject_Del(self);
+}
+
+extern int PyPath_Flatten(PyObject* data, double **xy);
+
+static PyObject*
+_draw_ink(ImagingDrawObject* self, PyObject* args)
+{
+ INT32 ink = 0;
+ PyObject* color;
+ char* mode = NULL; /* not used in this release */
+ if (!PyArg_ParseTuple(args, "O|s", &color, &mode))
+ return NULL;
+
+ if (!getink(color, self->image->image, (char*) &ink))
+ return NULL;
+
+ return PyInt_FromLong((int) ink);
+}
+
+static PyObject*
+_draw_arc(ImagingDrawObject* self, PyObject* args)
+{
+ int x0, y0, x1, y1;
+ int ink;
+ int start, end;
+ int op = 0;
+ if (!PyArg_ParseTuple(args, "(iiii)iii|i",
+ &x0, &y0, &x1, &y1,
+ &start, &end, &ink))
+ return NULL;
+
+ if (ImagingDrawArc(self->image->image, x0, y0, x1, y1, start, end,
+ &ink, op) < 0)
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_draw_bitmap(ImagingDrawObject* self, PyObject* args)
+{
+ double *xy;
+ int n;
+
+ PyObject *data;
+ ImagingObject* bitmap;
+ int ink;
+ if (!PyArg_ParseTuple(args, "OO!i", &data, &Imaging_Type, &bitmap, &ink))
+ return NULL;
+
+ n = PyPath_Flatten(data, &xy);
+ if (n < 0)
+ return NULL;
+ if (n != 1) {
+ PyErr_SetString(
+ PyExc_TypeError,
+ "coordinate list must contain exactly 1 coordinate"
+ );
+ return NULL;
+ }
+
+ n = ImagingDrawBitmap(
+ self->image->image, (int) xy[0], (int) xy[1], bitmap->image,
+ &ink, self->blend
+ );
+
+ free(xy);
+
+ if (n < 0)
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_draw_chord(ImagingDrawObject* self, PyObject* args)
+{
+ int x0, y0, x1, y1;
+ int ink, fill;
+ int start, end;
+ if (!PyArg_ParseTuple(args, "(iiii)iiii",
+ &x0, &y0, &x1, &y1, &start, &end, &ink, &fill))
+ return NULL;
+
+ if (ImagingDrawChord(self->image->image, x0, y0, x1, y1,
+ start, end, &ink, fill, self->blend) < 0)
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_draw_ellipse(ImagingDrawObject* self, PyObject* args)
+{
+ double* xy;
+ int n;
+
+ PyObject* data;
+ int ink;
+ int fill = 0;
+ if (!PyArg_ParseTuple(args, "Oi|i", &data, &ink, &fill))
+ return NULL;
+
+ n = PyPath_Flatten(data, &xy);
+ if (n < 0)
+ return NULL;
+ if (n != 2) {
+ PyErr_SetString(
+ PyExc_TypeError,
+ "coordinate list must contain exactly 2 coordinates"
+ );
+ return NULL;
+ }
+
+ n = ImagingDrawEllipse(
+ self->image->image, (int) xy[0], (int) xy[1], (int) xy[2], (int) xy[3],
+ &ink, fill, self->blend
+ );
+
+ free(xy);
+
+ if (n < 0)
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_draw_line(ImagingDrawObject* self, PyObject* args)
+{
+ int x0, y0, x1, y1;
+ int ink;
+ if (!PyArg_ParseTuple(args, "(ii)(ii)i", &x0, &y0, &x1, &y1, &ink))
+ return NULL;
+
+ if (ImagingDrawLine(self->image->image, x0, y0, x1, y1,
+ &ink, self->blend) < 0)
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_draw_lines(ImagingDrawObject* self, PyObject* args)
+{
+ double *xy;
+ int i, n;
+
+ PyObject *data;
+ int ink;
+ int width = 0;
+ if (!PyArg_ParseTuple(args, "Oi|i", &data, &ink, &width))
+ return NULL;
+
+ n = PyPath_Flatten(data, &xy);
+ if (n < 0)
+ return NULL;
+
+ if (width <= 1) {
+ double *p = NULL;
+ for (i = 0; i < n-1; i++) {
+ p = &xy[i+i];
+ if (ImagingDrawLine(
+ self->image->image,
+ (int) p[0], (int) p[1], (int) p[2], (int) p[3],
+ &ink, self->blend) < 0) {
+ free(xy);
+ return NULL;
+ }
+ }
+ if (p) /* draw last point */
+ ImagingDrawPoint(
+ self->image->image,
+ (int) p[2], (int) p[3],
+ &ink, self->blend
+ );
+ } else {
+ for (i = 0; i < n-1; i++) {
+ double *p = &xy[i+i];
+ if (ImagingDrawWideLine(
+ self->image->image,
+ (int) p[0], (int) p[1], (int) p[2], (int) p[3],
+ &ink, width, self->blend) < 0) {
+ free(xy);
+ return NULL;
+ }
+ }
+ }
+
+ free(xy);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_draw_point(ImagingDrawObject* self, PyObject* args)
+{
+ int x, y;
+ int ink;
+ if (!PyArg_ParseTuple(args, "(ii)i", &x, &y, &ink))
+ return NULL;
+
+ if (ImagingDrawPoint(self->image->image, x, y, &ink, self->blend) < 0)
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_draw_points(ImagingDrawObject* self, PyObject* args)
+{
+ double *xy;
+ int i, n;
+
+ PyObject *data;
+ int ink;
+ if (!PyArg_ParseTuple(args, "Oi", &data, &ink))
+ return NULL;
+
+ n = PyPath_Flatten(data, &xy);
+ if (n < 0)
+ return NULL;
+
+ for (i = 0; i < n; i++) {
+ double *p = &xy[i+i];
+ if (ImagingDrawPoint(self->image->image, (int) p[0], (int) p[1],
+ &ink, self->blend) < 0) {
+ free(xy);
+ return NULL;
+ }
+ }
+
+ free(xy);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+#ifdef WITH_ARROW
+
+/* from outline.c */
+extern ImagingOutline PyOutline_AsOutline(PyObject* outline);
+
+static PyObject*
+_draw_outline(ImagingDrawObject* self, PyObject* args)
+{
+ ImagingOutline outline;
+
+ PyObject* outline_;
+ int ink;
+ int fill = 0;
+ if (!PyArg_ParseTuple(args, "Oi|i", &outline_, &ink, &fill))
+ return NULL;
+
+ outline = PyOutline_AsOutline(outline_);
+ if (!outline) {
+ PyErr_SetString(PyExc_TypeError, "expected outline object");
+ return NULL;
+ }
+
+ if (ImagingDrawOutline(self->image->image, outline,
+ &ink, fill, self->blend) < 0)
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+#endif
+
+static PyObject*
+_draw_pieslice(ImagingDrawObject* self, PyObject* args)
+{
+ int x0, y0, x1, y1;
+ int ink, fill;
+ int start, end;
+ if (!PyArg_ParseTuple(args, "(iiii)iiii",
+ &x0, &y0, &x1, &y1, &start, &end, &ink, &fill))
+ return NULL;
+
+ if (ImagingDrawPieslice(self->image->image, x0, y0, x1, y1,
+ start, end, &ink, fill, self->blend) < 0)
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_draw_polygon(ImagingDrawObject* self, PyObject* args)
+{
+ double *xy;
+ int *ixy;
+ int n, i;
+
+ PyObject* data;
+ int ink;
+ int fill = 0;
+ if (!PyArg_ParseTuple(args, "Oi|i", &data, &ink, &fill))
+ return NULL;
+
+ n = PyPath_Flatten(data, &xy);
+ if (n < 0)
+ return NULL;
+ if (n < 2) {
+ PyErr_SetString(
+ PyExc_TypeError,
+ "coordinate list must contain at least 2 coordinates"
+ );
+ return NULL;
+ }
+
+ /* Copy list of vertices to array */
+ ixy = (int*) malloc(n * 2 * sizeof(int));
+
+ for (i = 0; i < n; i++) {
+ ixy[i+i] = (int) xy[i+i];
+ ixy[i+i+1] = (int) xy[i+i+1];
+ }
+
+ free(xy);
+
+ if (ImagingDrawPolygon(self->image->image, n, ixy,
+ &ink, fill, self->blend) < 0) {
+ free(ixy);
+ return NULL;
+ }
+
+ free(ixy);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_draw_rectangle(ImagingDrawObject* self, PyObject* args)
+{
+ double* xy;
+ int n;
+
+ PyObject* data;
+ int ink;
+ int fill = 0;
+ if (!PyArg_ParseTuple(args, "Oi|i", &data, &ink, &fill))
+ return NULL;
+
+ n = PyPath_Flatten(data, &xy);
+ if (n < 0)
+ return NULL;
+ if (n != 2) {
+ PyErr_SetString(
+ PyExc_TypeError,
+ "coordinate list must contain exactly 2 coordinates"
+ );
+ return NULL;
+ }
+
+ n = ImagingDrawRectangle(
+ self->image->image, (int) xy[0], (int) xy[1],
+ (int) xy[2], (int) xy[3], &ink, fill, self->blend
+ );
+
+ free(xy);
+
+ if (n < 0)
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static struct PyMethodDef _draw_methods[] = {
+#ifdef WITH_IMAGEDRAW
+ /* Graphics (ImageDraw) */
+ {"draw_line", (PyCFunction)_draw_line, 1},
+ {"draw_lines", (PyCFunction)_draw_lines, 1},
+#ifdef WITH_ARROW
+ {"draw_outline", (PyCFunction)_draw_outline, 1},
+#endif
+ {"draw_polygon", (PyCFunction)_draw_polygon, 1},
+ {"draw_rectangle", (PyCFunction)_draw_rectangle, 1},
+ {"draw_point", (PyCFunction)_draw_point, 1},
+ {"draw_points", (PyCFunction)_draw_points, 1},
+ {"draw_arc", (PyCFunction)_draw_arc, 1},
+ {"draw_bitmap", (PyCFunction)_draw_bitmap, 1},
+ {"draw_chord", (PyCFunction)_draw_chord, 1},
+ {"draw_ellipse", (PyCFunction)_draw_ellipse, 1},
+ {"draw_pieslice", (PyCFunction)_draw_pieslice, 1},
+ {"draw_ink", (PyCFunction)_draw_ink, 1},
+#endif
+ {NULL, NULL} /* sentinel */
+};
+
+static PyObject*
+_draw_getattr(ImagingDrawObject* self, char* name)
+{
+ return Py_FindMethod(_draw_methods, (PyObject*) self, name);
+}
+
+#endif
+
+
+static PyObject*
+pixel_access_new(ImagingObject* imagep, PyObject* args)
+{
+ PixelAccessObject *self;
+
+ int readonly = 0;
+ if (!PyArg_ParseTuple(args, "|i", &readonly))
+ return NULL;
+
+ self = PyObject_New(PixelAccessObject, &PixelAccess_Type);
+ if (self == NULL)
+ return NULL;
+
+ /* keep a reference to the image object */
+ Py_INCREF(imagep);
+ self->image = imagep;
+
+ self->readonly = readonly;
+
+ return (PyObject*) self;
+}
+
+static void
+pixel_access_dealloc(PixelAccessObject* self)
+{
+ Py_XDECREF(self->image);
+ PyObject_Del(self);
+}
+
+static PyObject *
+pixel_access_getitem(PixelAccessObject *self, PyObject *xy)
+{
+ int x, y;
+ if (_getxy(xy, &x, &y))
+ return NULL;
+
+ return getpixel(self->image->image, x, y);
+}
+
+static int
+pixel_access_setitem(PixelAccessObject *self, PyObject *xy, PyObject *color)
+{
+ Imaging im = self->image->image;
+ char ink[4];
+ int x, y;
+
+ if (self->readonly) {
+ ImagingError_ValueError(readonly);
+ return -1;
+ }
+
+ if (_getxy(xy, &x, &y))
+ return -1;
+
+ if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) {
+ PyErr_SetString(PyExc_IndexError, outside_image);
+ return -1;
+ }
+
+ if (!color) /* FIXME: raise exception? */
+ return 0;
+
+ if (!getink(color, im, ink))
+ return -1;
+
+ if (im->image8)
+ im->image8[y][x] = ink[0];
+ else
+ im->image32[y][x] = *((INT32*) ink);
+
+ return 0;
+}
+
+/* -------------------------------------------------------------------- */
+/* EFFECTS (experimental) */
+/* -------------------------------------------------------------------- */
+
+#ifdef WITH_EFFECTS
+
+static PyObject*
+_effect_mandelbrot(ImagingObject* self, PyObject* args)
+{
+ int xsize = 512;
+ int ysize = 512;
+ double extent[4];
+ int quality = 100;
+
+ extent[0] = -3; extent[1] = -2.5;
+ extent[2] = 2; extent[3] = 2.5;
+
+ if (!PyArg_ParseTuple(args, "|(ii)(dddd)i", &xsize, &ysize,
+ &extent[0], &extent[1], &extent[2], &extent[3],
+ &quality))
+ return NULL;
+
+ return PyImagingNew(ImagingEffectMandelbrot(xsize, ysize, extent, quality));
+}
+
+static PyObject*
+_effect_noise(ImagingObject* self, PyObject* args)
+{
+ int xsize, ysize;
+ float sigma = 128;
+ if (!PyArg_ParseTuple(args, "(ii)|f", &xsize, &ysize, &sigma))
+ return NULL;
+
+ return PyImagingNew(ImagingEffectNoise(xsize, ysize, sigma));
+}
+
+static PyObject*
+_effect_spread(ImagingObject* self, PyObject* args)
+{
+ int dist;
+
+ if (!PyArg_ParseTuple(args, "i", &dist))
+ return NULL;
+
+ return PyImagingNew(ImagingEffectSpread(self->image, dist));
+}
+
+#endif
+
+/* -------------------------------------------------------------------- */
+/* UTILITIES */
+/* -------------------------------------------------------------------- */
+
+static PyObject*
+_crc32(PyObject* self, PyObject* args)
+{
+ unsigned char* buffer;
+ int bytes;
+ int hi, lo;
+ UINT32 crc;
+
+ hi = lo = 0;
+
+ if (!PyArg_ParseTuple(args, "s#|(ii)", &buffer, &bytes, &hi, &lo))
+ return NULL;
+
+ crc = ((UINT32) (hi & 0xFFFF) << 16) + (lo & 0xFFFF);
+
+ crc = ImagingCRC32(crc, (unsigned char *)buffer, bytes);
+
+ return Py_BuildValue("ii", (crc >> 16) & 0xFFFF, crc & 0xFFFF);
+}
+
+static PyObject*
+_getcodecstatus(PyObject* self, PyObject* args)
+{
+ int status;
+ char* msg;
+
+ if (!PyArg_ParseTuple(args, "i", &status))
+ return NULL;
+
+ switch (status) {
+ case IMAGING_CODEC_OVERRUN:
+ msg = "buffer overrun."; break;
+ case IMAGING_CODEC_BROKEN:
+ msg = "broken data stream."; break;
+ case IMAGING_CODEC_UNKNOWN:
+ msg = "unrecognized data stream contents."; break;
+ case IMAGING_CODEC_CONFIG:
+ msg = "codec configuration error."; break;
+ case IMAGING_CODEC_MEMORY:
+ msg = "out of memory."; break;
+ default:
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return PyString_FromString(msg);
+}
+
+/* -------------------------------------------------------------------- */
+/* DEBUGGING HELPERS */
+/* -------------------------------------------------------------------- */
+
+
+#ifdef WITH_DEBUG
+
+static PyObject*
+_save_ppm(ImagingObject* self, PyObject* args)
+{
+ char* filename;
+
+ if (!PyArg_ParseTuple(args, "s", &filename))
+ return NULL;
+
+ if (!ImagingSavePPM(self->image, filename))
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+#endif
+
+/* -------------------------------------------------------------------- */
+
+/* methods */
+
+static struct PyMethodDef methods[] = {
+
+ /* Put commonly used methods first */
+ {"getpixel", (PyCFunction)_getpixel, 1},
+ {"putpixel", (PyCFunction)_putpixel, 1},
+
+ {"pixel_access", (PyCFunction)pixel_access_new, 1},
+
+ /* Standard processing methods (Image) */
+ {"convert", (PyCFunction)_convert, 1},
+ {"convert2", (PyCFunction)_convert2, 1},
+ {"convert_matrix", (PyCFunction)_convert_matrix, 1},
+ {"copy", (PyCFunction)_copy, 1},
+ {"copy2", (PyCFunction)_copy2, 1},
+#ifdef WITH_CRACKCODE
+ {"crackcode", (PyCFunction)_crackcode, 1},
+#endif
+ {"crop", (PyCFunction)_crop, 1},
+ {"expand", (PyCFunction)_expand, 1},
+ {"filter", (PyCFunction)_filter, 1},
+ {"histogram", (PyCFunction)_histogram, 1},
+#ifdef WITH_MODEFILTER
+ {"modefilter", (PyCFunction)_modefilter, 1},
+#endif
+ {"offset", (PyCFunction)_offset, 1},
+ {"paste", (PyCFunction)_paste, 1},
+ {"point", (PyCFunction)_point, 1},
+ {"point_transform", (PyCFunction)_point_transform, 1},
+ {"putdata", (PyCFunction)_putdata, 1},
+#ifdef WITH_QUANTIZE
+ {"quantize", (PyCFunction)_quantize, 1},
+#endif
+#ifdef WITH_RANKFILTER
+ {"rankfilter", (PyCFunction)_rankfilter, 1},
+#endif
+ {"resize", (PyCFunction)_resize, 1},
+ {"rotate", (PyCFunction)_rotate, 1},
+ {"stretch", (PyCFunction)_stretch, 1},
+ {"transpose", (PyCFunction)_transpose, 1},
+ {"transform2", (PyCFunction)_transform2, 1},
+
+ {"isblock", (PyCFunction)_isblock, 1},
+
+ {"getbbox", (PyCFunction)_getbbox, 1},
+ {"getcolors", (PyCFunction)_getcolors, 1},
+ {"getextrema", (PyCFunction)_getextrema, 1},
+ {"getprojection", (PyCFunction)_getprojection, 1},
+
+ {"getband", (PyCFunction)_getband, 1},
+ {"putband", (PyCFunction)_putband, 1},
+ {"fillband", (PyCFunction)_fillband, 1},
+
+ {"setmode", (PyCFunction)im_setmode, 1},
+
+ {"getpalette", (PyCFunction)_getpalette, 1},
+ {"putpalette", (PyCFunction)_putpalette, 1},
+ {"putpalettealpha", (PyCFunction)_putpalettealpha, 1},
+
+#ifdef WITH_IMAGECHOPS
+ /* Channel operations (ImageChops) */
+ {"chop_invert", (PyCFunction)_chop_invert, 1},
+ {"chop_lighter", (PyCFunction)_chop_lighter, 1},
+ {"chop_darker", (PyCFunction)_chop_darker, 1},
+ {"chop_difference", (PyCFunction)_chop_difference, 1},
+ {"chop_multiply", (PyCFunction)_chop_multiply, 1},
+ {"chop_screen", (PyCFunction)_chop_screen, 1},
+ {"chop_add", (PyCFunction)_chop_add, 1},
+ {"chop_subtract", (PyCFunction)_chop_subtract, 1},
+ {"chop_add_modulo", (PyCFunction)_chop_add_modulo, 1},
+ {"chop_subtract_modulo", (PyCFunction)_chop_subtract_modulo, 1},
+ {"chop_and", (PyCFunction)_chop_and, 1},
+ {"chop_or", (PyCFunction)_chop_or, 1},
+ {"chop_xor", (PyCFunction)_chop_xor, 1},
+#endif
+
+#ifdef WITH_EFFECTS
+ /* Special effects */
+ {"effect_spread", (PyCFunction)_effect_spread, 1},
+#endif
+
+ /* Misc. */
+ {"new_array", (PyCFunction)_new_array, 1},
+ {"new_block", (PyCFunction)_new_block, 1},
+
+#ifdef WITH_DEBUG
+ {"save_ppm", (PyCFunction)_save_ppm, 1},
+#endif
+
+ {NULL, NULL} /* sentinel */
+};
+
+
+/* attributes */
+
+static PyObject*
+_getattr(ImagingObject* self, char* name)
+{
+ PyObject* res;
+
+ res = Py_FindMethod(methods, (PyObject*) self, name);
+ if (res)
+ return res;
+ PyErr_Clear();
+ if (strcmp(name, "mode") == 0)
+ return PyString_FromString(self->image->mode);
+ if (strcmp(name, "size") == 0)
+ return Py_BuildValue("ii", self->image->xsize, self->image->ysize);
+ if (strcmp(name, "bands") == 0)
+ return PyInt_FromLong(self->image->bands);
+ if (strcmp(name, "id") == 0)
+ return PyInt_FromLong((long) self->image);
+ if (strcmp(name, "ptr") == 0)
+ return PyCObject_FromVoidPtrAndDesc(self->image, IMAGING_MAGIC, NULL);
+ PyErr_SetString(PyExc_AttributeError, name);
+ return NULL;
+}
+
+
+/* basic sequence semantics */
+
+static int
+image_length(ImagingObject *self)
+{
+ Imaging im = self->image;
+
+ return im->xsize * im->ysize;
+}
+
+static PyObject *
+image_item(ImagingObject *self, int i)
+{
+ int x, y;
+ Imaging im = self->image;
+
+ if (im->xsize > 0) {
+ x = i % im->xsize;
+ y = i / im->xsize;
+ } else
+ x = y = 0; /* leave it to getpixel to raise an exception */
+
+ return getpixel(im, x, y);
+}
+
+static PySequenceMethods image_as_sequence = {
+ (inquiry)image_length, /*sq_length*/
+ (binaryfunc)0, /*sq_concat*/
+ (ssizeargfunc)0, /*sq_repeat*/
+ (ssizeargfunc)image_item, /*sq_item*/
+ (ssizessizeargfunc)0, /*sq_slice*/
+ (ssizeobjargproc)0, /*sq_ass_item*/
+ (ssizessizeobjargproc)0, /*sq_ass_slice*/
+};
+
+
+/* type description */
+
+statichere PyTypeObject Imaging_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "ImagingCore", /*tp_name*/
+ sizeof(ImagingObject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor)_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ (getattrfunc)_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number */
+ &image_as_sequence, /*tp_as_sequence */
+ 0, /*tp_as_mapping */
+ 0 /*tp_hash*/
+};
+
+#ifdef WITH_IMAGEDRAW
+
+statichere PyTypeObject ImagingFont_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "ImagingFont", /*tp_name*/
+ sizeof(ImagingFontObject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor)_font_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ (getattrfunc)_font_getattr, /*tp_getattr*/
+};
+
+statichere PyTypeObject ImagingDraw_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "ImagingDraw", /*tp_name*/
+ sizeof(ImagingDrawObject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor)_draw_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ (getattrfunc)_draw_getattr, /*tp_getattr*/
+};
+
+#endif
+
+static PyMappingMethods pixel_access_as_mapping = {
+ (inquiry)0, /*mp_length*/
+ (binaryfunc)pixel_access_getitem, /*mp_subscript*/
+ (objobjargproc)pixel_access_setitem, /*mp_ass_subscript*/
+};
+
+/* type description */
+
+statichere PyTypeObject PixelAccess_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, "PixelAccess", sizeof(PixelAccessObject), 0,
+ /* methods */
+ (destructor)pixel_access_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number */
+ 0, /*tp_as_sequence */
+ &pixel_access_as_mapping, /*tp_as_mapping */
+ 0 /*tp_hash*/
+};
+
+/* -------------------------------------------------------------------- */
+
+/* FIXME: this is something of a mess. Should replace this with
+ pluggable codecs, but not before PIL 1.1 */
+
+/* Decoders (in decode.c) */
+extern PyObject* PyImaging_BitDecoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_FliDecoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_GifDecoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_HexDecoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_JpegDecoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_TiffLzwDecoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_MspDecoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_PackbitsDecoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_PcdDecoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_PcxDecoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_RawDecoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_SunRleDecoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_TgaRleDecoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_XbmDecoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_ZipDecoderNew(PyObject* self, PyObject* args);
+
+/* Encoders (in encode.c) */
+extern PyObject* PyImaging_EpsEncoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_GifEncoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_JpegEncoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_PcxEncoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_RawEncoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_XbmEncoderNew(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_ZipEncoderNew(PyObject* self, PyObject* args);
+
+/* Display support (in display.c) */
+#ifdef WIN32
+extern PyObject* PyImaging_CreateWindowWin32(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_DisplayWin32(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_DisplayModeWin32(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_GrabScreenWin32(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_GrabClipboardWin32(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_ListWindowsWin32(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_EventLoopWin32(PyObject* self, PyObject* args);
+#endif
+
+/* Experimental path stuff (in path.c) */
+extern PyObject* PyPath_Create(ImagingObject* self, PyObject* args);
+
+/* Experimental outline stuff (in outline.c) */
+extern PyObject* PyOutline_Create(ImagingObject* self, PyObject* args);
+
+extern PyObject* PyImaging_Mapper(PyObject* self, PyObject* args);
+extern PyObject* PyImaging_MapBuffer(PyObject* self, PyObject* args);
+
+static PyMethodDef functions[] = {
+
+ /* Object factories */
+ {"blend", (PyCFunction)_blend, 1},
+ {"fill", (PyCFunction)_fill, 1},
+ {"new", (PyCFunction)_new, 1},
+
+ {"getcount", (PyCFunction)_getcount, 1},
+
+ /* Functions */
+ {"convert", (PyCFunction)_convert2, 1},
+ {"copy", (PyCFunction)_copy2, 1},
+
+ /* Codecs */
+ {"bit_decoder", (PyCFunction)PyImaging_BitDecoderNew, 1},
+ {"eps_encoder", (PyCFunction)PyImaging_EpsEncoderNew, 1},
+ {"fli_decoder", (PyCFunction)PyImaging_FliDecoderNew, 1},
+ {"gif_decoder", (PyCFunction)PyImaging_GifDecoderNew, 1},
+ {"gif_encoder", (PyCFunction)PyImaging_GifEncoderNew, 1},
+ {"hex_decoder", (PyCFunction)PyImaging_HexDecoderNew, 1},
+ {"hex_encoder", (PyCFunction)PyImaging_EpsEncoderNew, 1}, /* EPS=HEX! */
+#ifdef HAVE_LIBJPEG
+ {"jpeg_decoder", (PyCFunction)PyImaging_JpegDecoderNew, 1},
+ {"jpeg_encoder", (PyCFunction)PyImaging_JpegEncoderNew, 1},
+#endif
+ {"tiff_lzw_decoder", (PyCFunction)PyImaging_TiffLzwDecoderNew, 1},
+ {"msp_decoder", (PyCFunction)PyImaging_MspDecoderNew, 1},
+ {"packbits_decoder", (PyCFunction)PyImaging_PackbitsDecoderNew, 1},
+ {"pcd_decoder", (PyCFunction)PyImaging_PcdDecoderNew, 1},
+ {"pcx_decoder", (PyCFunction)PyImaging_PcxDecoderNew, 1},
+ {"pcx_encoder", (PyCFunction)PyImaging_PcxEncoderNew, 1},
+ {"raw_decoder", (PyCFunction)PyImaging_RawDecoderNew, 1},
+ {"raw_encoder", (PyCFunction)PyImaging_RawEncoderNew, 1},
+ {"sun_rle_decoder", (PyCFunction)PyImaging_SunRleDecoderNew, 1},
+ {"tga_rle_decoder", (PyCFunction)PyImaging_TgaRleDecoderNew, 1},
+ {"xbm_decoder", (PyCFunction)PyImaging_XbmDecoderNew, 1},
+ {"xbm_encoder", (PyCFunction)PyImaging_XbmEncoderNew, 1},
+#ifdef HAVE_LIBZ
+ {"zip_decoder", (PyCFunction)PyImaging_ZipDecoderNew, 1},
+ {"zip_encoder", (PyCFunction)PyImaging_ZipEncoderNew, 1},
+#endif
+
+ /* Memory mapping */
+#ifdef WITH_MAPPING
+#ifdef WIN32
+ {"map", (PyCFunction)PyImaging_Mapper, 1},
+#endif
+ {"map_buffer", (PyCFunction)PyImaging_MapBuffer, 1},
+#endif
+
+ /* Display support */
+#ifdef WIN32
+ {"display", (PyCFunction)PyImaging_DisplayWin32, 1},
+ {"display_mode", (PyCFunction)PyImaging_DisplayModeWin32, 1},
+ {"grabscreen", (PyCFunction)PyImaging_GrabScreenWin32, 1},
+ {"grabclipboard", (PyCFunction)PyImaging_GrabClipboardWin32, 1},
+ {"createwindow", (PyCFunction)PyImaging_CreateWindowWin32, 1},
+ {"eventloop", (PyCFunction)PyImaging_EventLoopWin32, 1},
+ {"listwindows", (PyCFunction)PyImaging_ListWindowsWin32, 1},
+#endif
+
+ /* Utilities */
+ {"crc32", (PyCFunction)_crc32, 1},
+ {"getcodecstatus", (PyCFunction)_getcodecstatus, 1},
+
+ /* Debugging stuff */
+ {"open_ppm", (PyCFunction)_open_ppm, 1},
+
+ /* Special effects (experimental) */
+#ifdef WITH_EFFECTS
+ {"effect_mandelbrot", (PyCFunction)_effect_mandelbrot, 1},
+ {"effect_noise", (PyCFunction)_effect_noise, 1},
+ {"linear_gradient", (PyCFunction)_linear_gradient, 1},
+ {"radial_gradient", (PyCFunction)_radial_gradient, 1},
+ {"wedge", (PyCFunction)_linear_gradient, 1}, /* Compatibility */
+#endif
+
+ /* Drawing support stuff */
+#ifdef WITH_IMAGEDRAW
+ {"font", (PyCFunction)_font_new, 1},
+ {"draw", (PyCFunction)_draw_new, 1},
+#endif
+
+ /* Experimental path stuff */
+#ifdef WITH_IMAGEPATH
+ {"path", (PyCFunction)PyPath_Create, 1},
+#endif
+
+ /* Experimental arrow graphics stuff */
+#ifdef WITH_ARROW
+ {"outline", (PyCFunction)PyOutline_Create, 1},
+#endif
+
+ {NULL, NULL} /* sentinel */
+};
+
+DL_EXPORT(void)
+init_imaging(void)
+{
+ /* Patch object type */
+ Imaging_Type.ob_type = &PyType_Type;
+#ifdef WITH_IMAGEDRAW
+ ImagingFont_Type.ob_type = &PyType_Type;
+ ImagingDraw_Type.ob_type = &PyType_Type;
+#endif
+ PixelAccess_Type.ob_type = &PyType_Type;
+
+ Py_InitModule("_imaging", functions);
+}
diff --git a/Imaging/_imagingft.c b/Imaging/_imagingft.c
new file mode 100644
index 0000000..9ab8470
--- /dev/null
+++ b/Imaging/_imagingft.c
@@ -0,0 +1,463 @@
+/*
+ * PIL FreeType Driver
+ * $Id: _imagingft.c 2756 2006-06-19 06:07:18Z fredrik $
+ *
+ * a FreeType 2.X driver for PIL
+ *
+ * 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
+ * 2003-05-20 fl Fixed compilation under 1.5.2 and newer non-unicode builds
+ * 2003-09-27 fl Added charmap encoding support
+ * 2004-05-15 fl Fixed compilation for FreeType 2.1.8
+ * 2004-09-10 fl Added support for monochrome bitmaps
+ * 2006-06-18 fl Fixed glyph bearing calculation
+ *
+ * Copyright (c) 1998-2006 by Secret Labs AB
+ */
+
+#include "Python.h"
+#include "Imaging.h"
+
+#ifndef USE_FREETYPE_2_0
+/* undef/comment out to use freetype 2.0 */
+#define USE_FREETYPE_2_1
+#endif
+
+#if defined(USE_FREETYPE_2_1)
+/* freetype 2.1 and newer */
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#else
+/* freetype 2.0 */
+#include <freetype/freetype.h>
+#endif
+
+#if PY_VERSION_HEX < 0x01060000
+#define PyObject_New PyObject_NEW
+#define PyObject_Del PyMem_DEL
+#endif
+
+#if PY_VERSION_HEX >= 0x01060000
+#if PY_VERSION_HEX < 0x02020000 || defined(Py_USING_UNICODE)
+/* defining this enables unicode support (default under 1.6a1 and later) */
+#define HAVE_UNICODE
+#endif
+#endif
+
+#ifndef FT_LOAD_TARGET_MONO
+#define FT_LOAD_TARGET_MONO FT_LOAD_MONOCHROME
+#endif
+
+/* -------------------------------------------------------------------- */
+/* error table */
+
+#undef FTERRORS_H
+#undef __FTERRORS_H__
+
+#define FT_ERRORDEF( e, v, s ) { e, s },
+#define FT_ERROR_START_LIST {
+#define FT_ERROR_END_LIST { 0, 0 } };
+
+struct {
+ int code;
+ const char* message;
+} ft_errors[] =
+
+#include <freetype/fterrors.h>
+
+/* -------------------------------------------------------------------- */
+/* font objects */
+
+static FT_Library library;
+
+typedef struct {
+ PyObject_HEAD
+ FT_Face face;
+} FontObject;
+
+staticforward PyTypeObject Font_Type;
+
+/* round a 26.6 pixel coordinate to the nearest larger integer */
+#define PIXEL(x) ((((x)+63) & -64)>>6)
+
+static PyObject*
+geterror(int code)
+{
+ int i;
+
+ for (i = 0; ft_errors[i].message; i++)
+ if (ft_errors[i].code == code) {
+ PyErr_SetString(PyExc_IOError, ft_errors[i].message);
+ return NULL;
+ }
+
+ PyErr_SetString(PyExc_IOError, "unknown freetype error");
+ return NULL;
+}
+
+static PyObject*
+getfont(PyObject* self_, PyObject* args, PyObject* kw)
+{
+ /* create a font object from a file name and a size (in pixels) */
+
+ FontObject* self;
+ int error;
+
+ char* filename;
+ int size;
+ int index = 0;
+ unsigned char* encoding = NULL;
+ static char* kwlist[] = {
+ "filename", "size", "index", "encoding", NULL
+ };
+ if (!PyArg_ParseTupleAndKeywords(args, kw, "si|is", kwlist,
+ &filename, &size, &index, &encoding))
+ return NULL;
+
+ if (!library && FT_Init_FreeType(&library)) {
+ PyErr_SetString(
+ PyExc_IOError,
+ "cannot initialize FreeType library"
+ );
+ return NULL;
+ }
+
+ self = PyObject_New(FontObject, &Font_Type);
+ if (!self)
+ return NULL;
+
+ error = FT_New_Face(library, filename, index, &self->face);
+
+ if (!error)
+ error = FT_Set_Pixel_Sizes(self->face, 0, size);
+
+ if (!error && encoding && strlen((char*) encoding) == 4) {
+ FT_Encoding encoding_tag = FT_MAKE_TAG(
+ encoding[0], encoding[1], encoding[2], encoding[3]
+ );
+ error = FT_Select_Charmap(self->face, encoding_tag);
+ }
+
+ if (error) {
+ PyObject_Del(self);
+ return geterror(error);
+ }
+
+ return (PyObject*) self;
+}
+
+static int
+font_getchar(PyObject* string, int index, FT_ULong* char_out)
+{
+#if defined(HAVE_UNICODE)
+ if (PyUnicode_Check(string)) {
+ Py_UNICODE* p = PyUnicode_AS_UNICODE(string);
+ int size = PyUnicode_GET_SIZE(string);
+ if (index >= size)
+ return 0;
+ *char_out = p[index];
+ return 1;
+ }
+#endif
+ if (PyString_Check(string)) {
+ unsigned char* p = (unsigned char*) PyString_AS_STRING(string);
+ int size = PyString_GET_SIZE(string);
+ if (index >= size)
+ return 0;
+ *char_out = (unsigned char) p[index];
+ return 1;
+ }
+ return 0;
+}
+
+static PyObject*
+font_getsize(FontObject* self, PyObject* args)
+{
+ int i, x;
+ FT_ULong ch;
+ FT_Face face;
+ int xoffset;
+ FT_Bool kerning = FT_HAS_KERNING(self->face);
+ FT_UInt last_index = 0;
+
+ /* calculate size and bearing for a given string */
+
+ PyObject* string;
+ if (!PyArg_ParseTuple(args, "O:getsize", &string))
+ return NULL;
+
+#if defined(HAVE_UNICODE)
+ if (!PyUnicode_Check(string) && !PyString_Check(string)) {
+#else
+ if (!PyString_Check(string)) {
+#endif
+ PyErr_SetString(PyExc_TypeError, "expected string");
+ return NULL;
+ }
+
+ face = NULL;
+ xoffset = 0;
+
+ for (x = i = 0; font_getchar(string, i, &ch); i++) {
+ int index, error;
+ face = self->face;
+ index = FT_Get_Char_Index(face, ch);
+ if (kerning && last_index && index) {
+ FT_Vector delta;
+ FT_Get_Kerning(self->face, last_index, index, ft_kerning_default,
+ &delta);
+ x += delta.x;
+ }
+ error = FT_Load_Glyph(face, index, FT_LOAD_DEFAULT);
+ if (error)
+ return geterror(error);
+ if (i == 0)
+ xoffset = face->glyph->metrics.horiBearingX;
+ x += face->glyph->metrics.horiAdvance;
+ last_index = index;
+ }
+
+ if (face) {
+ int offset;
+ /* left bearing */
+ if (xoffset < 0)
+ x -= xoffset;
+ else
+ xoffset = 0;
+ /* right bearing */
+ offset = face->glyph->metrics.horiAdvance -
+ face->glyph->metrics.width -
+ face->glyph->metrics.horiBearingX;
+ if (offset < 0)
+ x -= offset;
+ }
+
+ return Py_BuildValue(
+ "(ii)(ii)",
+ PIXEL(x), PIXEL(self->face->size->metrics.height),
+ PIXEL(xoffset), 0
+ );
+}
+
+static PyObject*
+font_getabc(FontObject* self, PyObject* args)
+{
+ FT_ULong ch;
+ FT_Face face;
+ double a, b, c;
+
+ /* calculate ABC values for a given string */
+
+ PyObject* string;
+ if (!PyArg_ParseTuple(args, "O:getabc", &string))
+ return NULL;
+
+#if defined(HAVE_UNICODE)
+ if (!PyUnicode_Check(string) && !PyString_Check(string)) {
+#else
+ if (!PyString_Check(string)) {
+#endif
+ PyErr_SetString(PyExc_TypeError, "expected string");
+ return NULL;
+ }
+
+ if (font_getchar(string, 0, &ch)) {
+ int index, error;
+ face = self->face;
+ index = FT_Get_Char_Index(face, ch);
+ error = FT_Load_Glyph(face, index, FT_LOAD_DEFAULT);
+ if (error)
+ return geterror(error);
+ a = face->glyph->metrics.horiBearingX / 64.0;
+ b = face->glyph->metrics.width / 64.0;
+ c = (face->glyph->metrics.horiAdvance -
+ face->glyph->metrics.horiBearingX -
+ face->glyph->metrics.width) / 64.0;
+ } else
+ a = b = c = 0.0;
+
+ return Py_BuildValue("ddd", a, b, c);
+}
+
+static PyObject*
+font_render(FontObject* self, PyObject* args)
+{
+ int i, x, y;
+ Imaging im;
+ int index, error, ascender;
+ int load_flags;
+ unsigned char *source;
+ FT_ULong ch;
+ FT_GlyphSlot glyph;
+ FT_Bool kerning = FT_HAS_KERNING(self->face);
+ FT_UInt last_index = 0;
+
+ /* render string into given buffer (the buffer *must* have
+ the right size, or this will crash) */
+ PyObject* string;
+ long id;
+ int mask = 0;
+ if (!PyArg_ParseTuple(args, "Ol|i:render", &string, &id, &mask))
+ return NULL;
+
+#if defined(HAVE_UNICODE)
+ if (!PyUnicode_Check(string) && !PyString_Check(string)) {
+#else
+ if (!PyString_Check(string)) {
+#endif
+ PyErr_SetString(PyExc_TypeError, "expected string");
+ return NULL;
+ }
+
+ im = (Imaging) id;
+
+ load_flags = FT_LOAD_RENDER;
+ if (mask)
+ load_flags |= FT_LOAD_TARGET_MONO;
+
+ for (x = i = 0; font_getchar(string, i, &ch); i++) {
+ if (i == 0 && self->face->glyph->metrics.horiBearingX < 0)
+ x = PIXEL(self->face->glyph->metrics.horiBearingX);
+ index = FT_Get_Char_Index(self->face, ch);
+ if (kerning && last_index && index) {
+ FT_Vector delta;
+ FT_Get_Kerning(self->face, last_index, index, ft_kerning_default,
+ &delta);
+ x += delta.x >> 6;
+ }
+ error = FT_Load_Glyph(self->face, index, load_flags);
+ if (error)
+ return geterror(error);
+ glyph = self->face->glyph;
+ if (mask) {
+ /* use monochrome mask (on palette images, etc) */
+ int xx, x0, x1;
+ source = (unsigned char*) glyph->bitmap.buffer;
+ ascender = PIXEL(self->face->size->metrics.ascender);
+ xx = x + glyph->bitmap_left;
+ x0 = 0;
+ x1 = glyph->bitmap.width;
+ if (xx < 0)
+ x0 = -xx;
+ if (xx + x1 > im->xsize)
+ x1 = im->xsize - xx;
+ for (y = 0; y < glyph->bitmap.rows; y++) {
+ int yy = y + ascender - glyph->bitmap_top;
+ if (yy >= 0 && yy < im->ysize) {
+ /* blend this glyph into the buffer */
+ unsigned char *target = im->image8[yy] + xx;
+ int i, j, m = 128;
+ for (i = j = 0; j < x1; j++) {
+ if (j >= x0 && (source[i] & m))
+ target[j] = 255;
+ if (!(m >>= 1)) {
+ m = 128;
+ i++;
+ }
+ }
+ }
+ source += glyph->bitmap.pitch;
+ }
+ } else {
+ /* use antialiased rendering */
+ int xx, x0, x1;
+ source = (unsigned char*) glyph->bitmap.buffer;
+ ascender = PIXEL(self->face->size->metrics.ascender);
+ xx = x + glyph->bitmap_left;
+ x0 = 0;
+ x1 = glyph->bitmap.width;
+ if (xx < 0)
+ x0 = -xx;
+ if (xx + x1 > im->xsize)
+ x1 = im->xsize - xx;
+ for (y = 0; y < glyph->bitmap.rows; y++) {
+ int yy = y + ascender - glyph->bitmap_top;
+ if (yy >= 0 && yy < im->ysize) {
+ /* blend this glyph into the buffer */
+ int i;
+ unsigned char *target = im->image8[yy] + xx;
+ for (i = x0; i < x1; i++) {
+ if (target[i] < source[i])
+ target[i] = source[i];
+ }
+ }
+ source += glyph->bitmap.pitch;
+ }
+ }
+ x += PIXEL(glyph->metrics.horiAdvance);
+ last_index = index;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static void
+font_dealloc(FontObject* self)
+{
+ FT_Done_Face(self->face);
+ PyObject_Del(self);
+}
+
+static PyMethodDef font_methods[] = {
+ {"render", (PyCFunction) font_render, METH_VARARGS},
+ {"getsize", (PyCFunction) font_getsize, METH_VARARGS},
+ {"getabc", (PyCFunction) font_getabc, METH_VARARGS},
+ {NULL, NULL}
+};
+
+static PyObject*
+font_getattr(FontObject* self, char* name)
+{
+ PyObject* res;
+
+ res = Py_FindMethod(font_methods, (PyObject*) self, name);
+
+ if (res)
+ return res;
+
+ PyErr_Clear();
+
+ /* 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.descender));
+
+ 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;
+}
+
+statichere PyTypeObject Font_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, "Font", sizeof(FontObject), 0,
+ /* methods */
+ (destructor)font_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ (getattrfunc)font_getattr, /* tp_getattr */
+};
+
+static PyMethodDef _functions[] = {
+ {"getfont", (PyCFunction) getfont, METH_VARARGS|METH_KEYWORDS},
+ {NULL, NULL}
+};
+
+DL_EXPORT(void)
+init_imagingft(void)
+{
+ /* Patch object type */
+ Font_Type.ob_type = &PyType_Type;
+
+ Py_InitModule("_imagingft", _functions);
+}
diff --git a/Imaging/_imagingmath.c b/Imaging/_imagingmath.c
new file mode 100644
index 0000000..fdc5781
--- /dev/null
+++ b/Imaging/_imagingmath.c
@@ -0,0 +1,256 @@
+/*
+ * The Python Imaging Library
+ * $Id: _imagingmath.c 2396 2005-05-07 09:17:22Z Fredrik $
+ *
+ * a simple math add-on for the Python Imaging Library
+ *
+ * history:
+ * 1999-02-15 fl Created
+ * 2005-05-05 fl Simplified and cleaned up for PIL 1.1.6
+ *
+ * Copyright (c) 1999-2005 by Secret Labs AB
+ * Copyright (c) 2005 by Fredrik Lundh
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+#include "Python.h"
+
+#include "Imaging.h"
+
+#include "math.h"
+#include "float.h"
+
+#define UNOP(name, op, type)\
+void name(Imaging out, Imaging im1)\
+{\
+ int x, y;\
+ for (y = 0; y < out->ysize; y++) {\
+ type* p0 = (type*) out->image[y];\
+ type* p1 = (type*) im1->image[y];\
+ for (x = 0; x < out->xsize; x++) {\
+ *p0 = op(type, *p1);\
+ p0++; p1++;\
+ }\
+ }\
+}
+
+#define BINOP(name, op, type)\
+void name(Imaging out, Imaging im1, Imaging im2)\
+{\
+ int x, y;\
+ for (y = 0; y < out->ysize; y++) {\
+ type* p0 = (type*) out->image[y];\
+ type* p1 = (type*) im1->image[y];\
+ type* p2 = (type*) im2->image[y];\
+ for (x = 0; x < out->xsize; x++) {\
+ *p0 = op(type, *p1, *p2);\
+ p0++; p1++; p2++;\
+ }\
+ }\
+}
+
+#define NEG(type, v1) -(v1)
+#define INVERT(type, v1) ~(v1)
+
+#define ADD(type, v1, v2) (v1)+(v2)
+#define SUB(type, v1, v2) (v1)-(v2)
+#define MUL(type, v1, v2) (v1)*(v2)
+
+#define MIN(type, v1, v2) ((v1)<(v2))?(v1):(v2)
+#define MAX(type, v1, v2) ((v1)>(v2))?(v1):(v2)
+
+#define AND(type, v1, v2) (v1)&(v2)
+#define OR(type, v1, v2) (v1)|(v2)
+#define XOR(type, v1, v2) (v1)^(v2)
+#define LSHIFT(type, v1, v2) (v1)<<(v2)
+#define RSHIFT(type, v1, v2) (v1)>>(v2)
+
+#define ABS_I(type, v1) abs((v1))
+#define ABS_F(type, v1) fabs((v1))
+
+/* --------------------------------------------------------------------
+ * some day, we should add FPE protection mechanisms. see pyfpe.h for
+ * details.
+ *
+ * PyFPE_START_PROTECT("Error in foobar", return 0)
+ * PyFPE_END_PROTECT(result)
+ */
+
+#define DIV_I(type, v1, v2) ((v2)!=0)?(v1)/(v2):0
+#define DIV_F(type, v1, v2) ((v2)!=0.0F)?(v1)/(v2):0.0F
+
+#define MOD_I(type, v1, v2) ((v2)!=0)?(v1)%(v2):0
+#define MOD_F(type, v1, v2) ((v2)!=0.0F)?fmod((v1),(v2)):0.0F
+
+#define DIFF_I(type, v1, v2) abs((v1)-(v2))
+#define DIFF_F(type, v1, v2) fabs((v1)-(v2))
+
+#define EQ(type, v1, v2) (v1)==(v2)
+#define NE(type, v1, v2) (v1)!=(v2)
+#define LT(type, v1, v2) (v1)<(v2)
+#define LE(type, v1, v2) (v1)<=(v2)
+#define GT(type, v1, v2) (v1)>(v2)
+#define GE(type, v1, v2) (v1)>=(v2)
+
+UNOP(abs_I, ABS_I, INT32)
+UNOP(neg_I, NEG, INT32)
+
+BINOP(add_I, ADD, INT32)
+BINOP(sub_I, SUB, INT32)
+BINOP(mul_I, MUL, INT32)
+BINOP(div_I, DIV_I, INT32)
+BINOP(mod_I, MOD_I, INT32)
+BINOP(diff_I, DIFF_I, INT32)
+
+UNOP(invert_I, INVERT, INT32)
+BINOP(and_I, AND, INT32)
+BINOP(or_I, OR, INT32)
+BINOP(xor_I, XOR, INT32)
+BINOP(lshift_I, LSHIFT, INT32)
+BINOP(rshift_I, RSHIFT, INT32)
+
+BINOP(min_I, MIN, INT32)
+BINOP(max_I, MAX, INT32)
+
+BINOP(eq_I, EQ, INT32)
+BINOP(ne_I, NE, INT32)
+BINOP(lt_I, LT, INT32)
+BINOP(le_I, LE, INT32)
+BINOP(gt_I, GT, INT32)
+BINOP(ge_I, GE, INT32)
+
+UNOP(abs_F, ABS_F, FLOAT32)
+UNOP(neg_F, NEG, FLOAT32)
+
+BINOP(add_F, ADD, FLOAT32)
+BINOP(sub_F, SUB, FLOAT32)
+BINOP(mul_F, MUL, FLOAT32)
+BINOP(div_F, DIV_F, FLOAT32)
+BINOP(mod_F, MOD_F, FLOAT32)
+BINOP(diff_F, DIFF_F, FLOAT32)
+
+BINOP(min_F, MIN, FLOAT32)
+BINOP(max_F, MAX, FLOAT32)
+
+BINOP(eq_F, EQ, FLOAT32)
+BINOP(ne_F, NE, FLOAT32)
+BINOP(lt_F, LT, FLOAT32)
+BINOP(le_F, LE, FLOAT32)
+BINOP(gt_F, GT, FLOAT32)
+BINOP(ge_F, GE, FLOAT32)
+
+static PyObject *
+_unop(PyObject* self, PyObject* args)
+{
+ Imaging out;
+ Imaging im1;
+ void (*unop)(Imaging, Imaging);
+
+ long op, i0, i1;
+ if (!PyArg_ParseTuple(args, "lll", &op, &i0, &i1))
+ return NULL;
+
+ out = (Imaging) i0;
+ im1 = (Imaging) i1;
+
+ unop = (void*) op;
+
+ unop(out, im1);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_binop(PyObject* self, PyObject* args)
+{
+ Imaging out;
+ Imaging im1;
+ Imaging im2;
+ void (*binop)(Imaging, Imaging, Imaging);
+
+ long op, i0, i1, i2;
+ if (!PyArg_ParseTuple(args, "llll", &op, &i0, &i1, &i2))
+ return NULL;
+
+ out = (Imaging) i0;
+ im1 = (Imaging) i1;
+ im2 = (Imaging) i2;
+
+ binop = (void*) op;
+
+ binop(out, im1, im2);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyMethodDef _functions[] = {
+ {"unop", _unop, 1},
+ {"binop", _binop, 1},
+ {NULL, NULL}
+};
+
+static void
+install(PyObject *d, char* name, void* value)
+{
+ PyObject *v = PyInt_FromLong((long) value);
+ if (!v || PyDict_SetItemString(d, name, v))
+ PyErr_Clear();
+ Py_XDECREF(v);
+}
+
+DL_EXPORT(void)
+init_imagingmath(void)
+{
+ PyObject* m;
+ PyObject* d;
+
+ m = Py_InitModule("_imagingmath", _functions);
+ d = PyModule_GetDict(m);
+
+ install(d, "abs_I", abs_I);
+ install(d, "neg_I", neg_I);
+ install(d, "add_I", add_I);
+ install(d, "sub_I", sub_I);
+ install(d, "diff_I", diff_I);
+ install(d, "mul_I", mul_I);
+ install(d, "div_I", div_I);
+ install(d, "mod_I", mod_I);
+ install(d, "min_I", min_I);
+ install(d, "max_I", max_I);
+
+ install(d, "invert_I", invert_I);
+ install(d, "and_I", and_I);
+ install(d, "or_I", or_I);
+ install(d, "xor_I", xor_I);
+ install(d, "lshift_I", lshift_I);
+ install(d, "rshift_I", rshift_I);
+
+ install(d, "eq_I", eq_I);
+ install(d, "ne_I", ne_I);
+ install(d, "lt_I", lt_I);
+ install(d, "le_I", le_I);
+ install(d, "gt_I", gt_I);
+ install(d, "ge_I", ge_I);
+
+ install(d, "abs_F", abs_F);
+ install(d, "neg_F", neg_F);
+ install(d, "add_F", add_F);
+ install(d, "sub_F", sub_F);
+ install(d, "diff_F", diff_F);
+ install(d, "mul_F", mul_F);
+ install(d, "div_F", div_F);
+ install(d, "mod_F", mod_F);
+ install(d, "min_F", min_F);
+ install(d, "max_F", max_F);
+
+ install(d, "eq_F", eq_F);
+ install(d, "ne_F", ne_F);
+ install(d, "lt_F", lt_F);
+ install(d, "le_F", le_F);
+ install(d, "gt_F", gt_F);
+ install(d, "ge_F", ge_F);
+
+}
diff --git a/Imaging/_imagingtk.c b/Imaging/_imagingtk.c
new file mode 100644
index 0000000..5e8a94a
--- /dev/null
+++ b/Imaging/_imagingtk.c
@@ -0,0 +1,71 @@
+/*
+ * The Python Imaging Library.
+ * $Id: _imagingtk.c 1756 2004-03-28 17:15:33Z fredrik $
+ *
+ * tkinter hooks
+ *
+ * history:
+ * 99-07-26 fl created
+ * 99-08-15 fl moved to its own support module
+ *
+ * Copyright (c) Secret Labs AB 1999.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Python.h"
+#include "Imaging.h"
+
+#include "tk.h"
+
+/* must link with Tk/tkImaging.c */
+extern void TkImaging_Init(Tcl_Interp* interp);
+
+/* copied from _tkinter.c (this isn't as bad as it may seem: for new
+ versions, we use _tkinter's interpaddr hook instead, and all older
+ versions use this structure layout) */
+
+typedef struct {
+ PyObject_HEAD
+ Tcl_Interp* interp;
+} TkappObject;
+
+static PyObject*
+_tkinit(PyObject* self, PyObject* args)
+{
+ Tcl_Interp* interp;
+
+ long arg;
+ int is_interp;
+ if (!PyArg_ParseTuple(args, "li", &arg, &is_interp))
+ return NULL;
+
+ if (is_interp)
+ interp = (Tcl_Interp*) arg;
+ else {
+ TkappObject* app;
+ /* Do it the hard way. This will break if the TkappObject
+ layout changes */
+ app = (TkappObject*) arg;
+ interp = app->interp;
+ }
+
+ /* This will bomb if interp is invalid... */
+ TkImaging_Init(interp);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyMethodDef functions[] = {
+ /* Tkinter interface stuff */
+ {"tkinit", (PyCFunction)_tkinit, 1},
+ {NULL, NULL} /* sentinel */
+};
+
+DL_EXPORT(void)
+init_imagingtk(void)
+{
+ Py_InitModule("_imagingtk", functions);
+}
diff --git a/Imaging/decode.c b/Imaging/decode.c
new file mode 100644
index 0000000..89d1c3b
--- /dev/null
+++ b/Imaging/decode.c
@@ -0,0 +1,689 @@
+/*
+ * The Python Imaging Library.
+ * $Id: decode.c 2751 2006-06-18 19:50:45Z fredrik $
+ *
+ * standard decoder interfaces for the Imaging library
+ *
+ * history:
+ * 1996-03-28 fl Moved from _imagingmodule.c
+ * 1996-04-15 fl Support subregions in setimage
+ * 1996-04-19 fl Allocate decoder buffer (where appropriate)
+ * 1996-05-02 fl Added jpeg decoder
+ * 1996-05-12 fl Compile cleanly as C++
+ * 1996-05-16 fl Added hex decoder
+ * 1996-05-26 fl Added jpeg configuration parameters
+ * 1996-12-14 fl Added zip decoder
+ * 1996-12-30 fl Plugged potential memory leak for tiled images
+ * 1997-01-03 fl Added fli and msp decoders
+ * 1997-01-04 fl Added sun_rle and tga_rle decoders
+ * 1997-05-31 fl Added bitfield decoder
+ * 1998-09-11 fl Added orientation and pixelsize fields to tga_rle decoder
+ * 1998-12-29 fl Added mode/rawmode argument to decoders
+ * 1998-12-30 fl Added mode argument to *all* decoders
+ * 2002-06-09 fl Added stride argument to pcx decoder
+ *
+ * Copyright (c) 1997-2002 by Secret Labs AB.
+ * Copyright (c) 1995-2002 by Fredrik Lundh.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+/* FIXME: make these pluggable! */
+
+#include "Python.h"
+
+#if PY_VERSION_HEX < 0x01060000
+#define PyObject_New PyObject_NEW
+#define PyObject_Del PyMem_DEL
+#endif
+
+#include "Imaging.h"
+
+#include "Gif.h"
+#include "Lzw.h"
+#include "Raw.h"
+#include "Bit.h"
+
+
+/* -------------------------------------------------------------------- */
+/* Common */
+/* -------------------------------------------------------------------- */
+
+typedef struct {
+ PyObject_HEAD
+ int (*decode)(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+ struct ImagingCodecStateInstance state;
+ Imaging im;
+ PyObject* lock;
+} ImagingDecoderObject;
+
+staticforward PyTypeObject ImagingDecoderType;
+
+static ImagingDecoderObject*
+PyImaging_DecoderNew(int contextsize)
+{
+ ImagingDecoderObject *decoder;
+ void *context;
+
+ ImagingDecoderType.ob_type = &PyType_Type;
+
+ decoder = PyObject_New(ImagingDecoderObject, &ImagingDecoderType);
+ if (decoder == NULL)
+ return NULL;
+
+ /* Clear the decoder state */
+ memset(&decoder->state, 0, sizeof(decoder->state));
+
+ /* Allocate decoder context */
+ if (contextsize > 0) {
+ context = (void*) calloc(1, contextsize);
+ if (!context) {
+ Py_DECREF(decoder);
+ PyErr_NoMemory();
+ return NULL;
+ }
+ } else
+ context = 0;
+
+ /* Initialize decoder context */
+ decoder->state.context = context;
+
+ /* Target image */
+ decoder->lock = NULL;
+ decoder->im = NULL;
+
+ return decoder;
+}
+
+static void
+_dealloc(ImagingDecoderObject* decoder)
+{
+ free(decoder->state.buffer);
+ free(decoder->state.context);
+ Py_XDECREF(decoder->lock);
+ PyObject_Del(decoder);
+}
+
+static PyObject*
+_decode(ImagingDecoderObject* decoder, PyObject* args)
+{
+ UINT8* buffer;
+ int bufsize, status;
+
+ if (!PyArg_ParseTuple(args, "s#", &buffer, &bufsize))
+ return NULL;
+
+ status = decoder->decode(decoder->im, &decoder->state, buffer, bufsize);
+
+ return Py_BuildValue("ii", status, decoder->state.errcode);
+}
+
+extern Imaging PyImaging_AsImaging(PyObject *op);
+
+static PyObject*
+_setimage(ImagingDecoderObject* decoder, PyObject* args)
+{
+ PyObject* op;
+ Imaging im;
+ ImagingCodecState state;
+ int x0, y0, x1, y1;
+
+ x0 = y0 = x1 = y1 = 0;
+
+ /* FIXME: should publish the ImagingType descriptor */
+ if (!PyArg_ParseTuple(args, "O|(iiii)", &op, &x0, &y0, &x1, &y1))
+ return NULL;
+ im = PyImaging_AsImaging(op);
+ if (!im)
+ return NULL;
+
+ decoder->im = im;
+
+ state = &decoder->state;
+
+ /* Setup decoding tile extent */
+ if (x0 == 0 && x1 == 0) {
+ state->xsize = im->xsize;
+ state->ysize = im->ysize;
+ } else {
+ state->xoff = x0;
+ state->yoff = y0;
+ state->xsize = x1 - x0;
+ state->ysize = y1 - y0;
+ }
+
+ if (state->xsize <= 0 ||
+ state->xsize + state->xoff > (int) im->xsize ||
+ state->ysize <= 0 ||
+ state->ysize + state->yoff > (int) im->ysize) {
+ PyErr_SetString(PyExc_ValueError, "tile cannot extend outside image");
+ return NULL;
+ }
+
+ /* Allocate memory buffer (if bits field is set) */
+ if (state->bits > 0) {
+ if (!state->bytes)
+ state->bytes = (state->bits * state->xsize+7)/8;
+ state->buffer = (UINT8*) malloc(state->bytes);
+ if (!state->buffer) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ }
+
+ /* Keep a reference to the image object, to make sure it doesn't
+ go away before we do */
+ Py_INCREF(op);
+ Py_XDECREF(decoder->lock);
+ decoder->lock = op;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static struct PyMethodDef methods[] = {
+ {"decode", (PyCFunction)_decode, 1},
+ {"setimage", (PyCFunction)_setimage, 1},
+ {NULL, NULL} /* sentinel */
+};
+
+static PyObject*
+_getattr(ImagingDecoderObject* self, char* name)
+{
+ return Py_FindMethod(methods, (PyObject*) self, name);
+}
+
+statichere PyTypeObject ImagingDecoderType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "ImagingDecoder", /*tp_name*/
+ sizeof(ImagingDecoderObject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor)_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ (getattrfunc)_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_hash*/
+};
+
+/* -------------------------------------------------------------------- */
+
+int
+get_unpacker(ImagingDecoderObject* decoder, const char* mode,
+ const char* rawmode)
+{
+ int bits;
+ ImagingShuffler unpack;
+
+ unpack = ImagingFindUnpacker(mode, rawmode, &bits);
+ if (!unpack) {
+ Py_DECREF(decoder);
+ PyErr_SetString(PyExc_ValueError, "unknown raw mode");
+ return -1;
+ }
+
+ decoder->state.shuffle = unpack;
+ decoder->state.bits = bits;
+
+ return 0;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* BIT (packed fields) */
+/* -------------------------------------------------------------------- */
+
+PyObject*
+PyImaging_BitDecoderNew(PyObject* self, PyObject* args)
+{
+ ImagingDecoderObject* decoder;
+
+ char* mode;
+ int bits = 8;
+ int pad = 8;
+ int fill = 0;
+ int sign = 0;
+ int ystep = 1;
+ if (!PyArg_ParseTuple(args, "s|iiiii", &mode, &bits, &pad, &fill,
+ &sign, &ystep))
+ return NULL;
+
+ if (strcmp(mode, "F") != 0) {
+ PyErr_SetString(PyExc_ValueError, "bad image mode");
+ return NULL;
+ }
+
+ decoder = PyImaging_DecoderNew(sizeof(BITSTATE));
+ if (decoder == NULL)
+ return NULL;
+
+ decoder->decode = ImagingBitDecode;
+
+ decoder->state.ystep = ystep;
+
+ ((BITSTATE*)decoder->state.context)->bits = bits;
+ ((BITSTATE*)decoder->state.context)->pad = pad;
+ ((BITSTATE*)decoder->state.context)->fill = fill;
+ ((BITSTATE*)decoder->state.context)->sign = sign;
+
+ return (PyObject*) decoder;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* FLI */
+/* -------------------------------------------------------------------- */
+
+PyObject*
+PyImaging_FliDecoderNew(PyObject* self, PyObject* args)
+{
+ ImagingDecoderObject* decoder;
+
+ decoder = PyImaging_DecoderNew(0);
+ if (decoder == NULL)
+ return NULL;
+
+ decoder->decode = ImagingFliDecode;
+
+ return (PyObject*) decoder;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* GIF */
+/* -------------------------------------------------------------------- */
+
+PyObject*
+PyImaging_GifDecoderNew(PyObject* self, PyObject* args)
+{
+ ImagingDecoderObject* decoder;
+
+ char* mode;
+ int bits = 8;
+ int interlace = 0;
+ if (!PyArg_ParseTuple(args, "s|ii", &mode, &bits, &interlace))
+ return NULL;
+
+ if (strcmp(mode, "L") != 0 && strcmp(mode, "P") != 0) {
+ PyErr_SetString(PyExc_ValueError, "bad image mode");
+ return NULL;
+ }
+
+ decoder = PyImaging_DecoderNew(sizeof(GIFDECODERSTATE));
+ if (decoder == NULL)
+ return NULL;
+
+ decoder->decode = ImagingGifDecode;
+
+ ((GIFDECODERSTATE*)decoder->state.context)->bits = bits;
+ ((GIFDECODERSTATE*)decoder->state.context)->interlace = interlace;
+
+ return (PyObject*) decoder;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* HEX */
+/* -------------------------------------------------------------------- */
+
+PyObject*
+PyImaging_HexDecoderNew(PyObject* self, PyObject* args)
+{
+ ImagingDecoderObject* decoder;
+
+ char* mode;
+ char* rawmode;
+ if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode))
+ return NULL;
+
+ decoder = PyImaging_DecoderNew(0);
+ if (decoder == NULL)
+ return NULL;
+
+ if (get_unpacker(decoder, mode, rawmode) < 0)
+ return NULL;
+
+ decoder->decode = ImagingHexDecode;
+
+ return (PyObject*) decoder;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* LZW */
+/* -------------------------------------------------------------------- */
+
+PyObject*
+PyImaging_TiffLzwDecoderNew(PyObject* self, PyObject* args)
+{
+ ImagingDecoderObject* decoder;
+
+ char* mode;
+ char* rawmode;
+ int filter = 0;
+ if (!PyArg_ParseTuple(args, "ss|i", &mode, &rawmode, &filter))
+ return NULL;
+
+ decoder = PyImaging_DecoderNew(sizeof(LZWSTATE));
+ if (decoder == NULL)
+ return NULL;
+
+ if (get_unpacker(decoder, mode, rawmode) < 0)
+ return NULL;
+
+ decoder->decode = ImagingLzwDecode;
+
+ ((LZWSTATE*)decoder->state.context)->filter = filter;
+
+ return (PyObject*) decoder;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* MSP */
+/* -------------------------------------------------------------------- */
+
+PyObject*
+PyImaging_MspDecoderNew(PyObject* self, PyObject* args)
+{
+ ImagingDecoderObject* decoder;
+
+ decoder = PyImaging_DecoderNew(0);
+ if (decoder == NULL)
+ return NULL;
+
+ if (get_unpacker(decoder, "1", "1") < 0)
+ return NULL;
+
+ decoder->decode = ImagingMspDecode;
+
+ return (PyObject*) decoder;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* PackBits */
+/* -------------------------------------------------------------------- */
+
+PyObject*
+PyImaging_PackbitsDecoderNew(PyObject* self, PyObject* args)
+{
+ ImagingDecoderObject* decoder;
+
+ char* mode;
+ char* rawmode;
+ if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode))
+ return NULL;
+
+ decoder = PyImaging_DecoderNew(0);
+ if (decoder == NULL)
+ return NULL;
+
+ if (get_unpacker(decoder, mode, rawmode) < 0)
+ return NULL;
+
+ decoder->decode = ImagingPackbitsDecode;
+
+ return (PyObject*) decoder;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* PCD */
+/* -------------------------------------------------------------------- */
+
+PyObject*
+PyImaging_PcdDecoderNew(PyObject* self, PyObject* args)
+{
+ ImagingDecoderObject* decoder;
+
+ decoder = PyImaging_DecoderNew(0);
+ if (decoder == NULL)
+ return NULL;
+
+ /* Unpack from PhotoYCC to RGB */
+ if (get_unpacker(decoder, "RGB", "YCC;P") < 0)
+ return NULL;
+
+ decoder->decode = ImagingPcdDecode;
+
+ return (PyObject*) decoder;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* PCX */
+/* -------------------------------------------------------------------- */
+
+PyObject*
+PyImaging_PcxDecoderNew(PyObject* self, PyObject* args)
+{
+ ImagingDecoderObject* decoder;
+
+ char* mode;
+ char* rawmode;
+ int stride;
+ if (!PyArg_ParseTuple(args, "ssi", &mode, &rawmode, &stride))
+ return NULL;
+
+ decoder = PyImaging_DecoderNew(0);
+ if (decoder == NULL)
+ return NULL;
+
+ if (get_unpacker(decoder, mode, rawmode) < 0)
+ return NULL;
+
+ decoder->state.bytes = stride;
+
+ decoder->decode = ImagingPcxDecode;
+
+ return (PyObject*) decoder;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* RAW */
+/* -------------------------------------------------------------------- */
+
+PyObject*
+PyImaging_RawDecoderNew(PyObject* self, PyObject* args)
+{
+ ImagingDecoderObject* decoder;
+
+ char* mode;
+ char* rawmode;
+ int stride = 0;
+ int ystep = 1;
+ if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &stride, &ystep))
+ return NULL;
+
+ decoder = PyImaging_DecoderNew(sizeof(RAWSTATE));
+ if (decoder == NULL)
+ return NULL;
+
+ if (get_unpacker(decoder, mode, rawmode) < 0)
+ return NULL;
+
+ decoder->decode = ImagingRawDecode;
+
+ decoder->state.ystep = ystep;
+
+ ((RAWSTATE*)decoder->state.context)->stride = stride;
+
+ return (PyObject*) decoder;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* SUN RLE */
+/* -------------------------------------------------------------------- */
+
+PyObject*
+PyImaging_SunRleDecoderNew(PyObject* self, PyObject* args)
+{
+ ImagingDecoderObject* decoder;
+
+ char* mode;
+ char* rawmode;
+ if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode))
+ return NULL;
+
+ decoder = PyImaging_DecoderNew(0);
+ if (decoder == NULL)
+ return NULL;
+
+ if (get_unpacker(decoder, mode, rawmode) < 0)
+ return NULL;
+
+ decoder->decode = ImagingSunRleDecode;
+
+ return (PyObject*) decoder;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* TGA RLE */
+/* -------------------------------------------------------------------- */
+
+PyObject*
+PyImaging_TgaRleDecoderNew(PyObject* self, PyObject* args)
+{
+ ImagingDecoderObject* decoder;
+
+ char* mode;
+ char* rawmode;
+ int ystep = 1;
+ int depth = 8;
+ if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &ystep, &depth))
+ return NULL;
+
+ decoder = PyImaging_DecoderNew(0);
+ if (decoder == NULL)
+ return NULL;
+
+ if (get_unpacker(decoder, mode, rawmode) < 0)
+ return NULL;
+
+ decoder->decode = ImagingTgaRleDecode;
+
+ decoder->state.ystep = ystep;
+ decoder->state.count = depth / 8;
+
+ return (PyObject*) decoder;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* XBM */
+/* -------------------------------------------------------------------- */
+
+PyObject*
+PyImaging_XbmDecoderNew(PyObject* self, PyObject* args)
+{
+ ImagingDecoderObject* decoder;
+
+ decoder = PyImaging_DecoderNew(0);
+ if (decoder == NULL)
+ return NULL;
+
+ if (get_unpacker(decoder, "1", "1;R") < 0)
+ return NULL;
+
+ decoder->decode = ImagingXbmDecode;
+
+ return (PyObject*) decoder;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* ZIP */
+/* -------------------------------------------------------------------- */
+
+#ifdef HAVE_LIBZ
+
+#include "Zip.h"
+
+PyObject*
+PyImaging_ZipDecoderNew(PyObject* self, PyObject* args)
+{
+ ImagingDecoderObject* decoder;
+
+ char* mode;
+ char* rawmode;
+ if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode))
+ return NULL;
+
+ decoder = PyImaging_DecoderNew(sizeof(ZIPSTATE));
+ if (decoder == NULL)
+ return NULL;
+
+ if (get_unpacker(decoder, mode, rawmode) < 0)
+ return NULL;
+
+ decoder->decode = ImagingZipDecode;
+
+ return (PyObject*) decoder;
+}
+#endif
+
+
+/* -------------------------------------------------------------------- */
+/* JPEG */
+/* -------------------------------------------------------------------- */
+
+#ifdef HAVE_LIBJPEG
+
+/* We better define this decoder last in this file, so the following
+ undef's won't mess things up for the Imaging library proper. */
+
+#undef HAVE_PROTOTYPES
+#undef HAVE_STDDEF_H
+#undef HAVE_STDLIB_H
+#undef UINT8
+#undef UINT16
+#undef UINT32
+#undef INT8
+#undef INT16
+#undef INT32
+
+#include "Jpeg.h"
+
+PyObject*
+PyImaging_JpegDecoderNew(PyObject* self, PyObject* args)
+{
+ ImagingDecoderObject* decoder;
+
+ char* mode;
+ char* rawmode; /* what we wan't from the decoder */
+ char* jpegmode; /* what's in the file */
+ int scale = 1;
+ int draft = 0;
+ if (!PyArg_ParseTuple(args, "ssz|ii", &mode, &rawmode, &jpegmode,
+ &scale, &draft))
+ return NULL;
+
+ if (!jpegmode)
+ jpegmode = "";
+
+ decoder = PyImaging_DecoderNew(sizeof(JPEGSTATE));
+ if (decoder == NULL)
+ return NULL;
+
+ if (get_unpacker(decoder, mode, rawmode) < 0)
+ return NULL;
+
+ decoder->decode = ImagingJpegDecode;
+
+ strncpy(((JPEGSTATE*)decoder->state.context)->rawmode, rawmode, 8);
+ strncpy(((JPEGSTATE*)decoder->state.context)->jpegmode, jpegmode, 8);
+
+ ((JPEGSTATE*)decoder->state.context)->scale = scale;
+ ((JPEGSTATE*)decoder->state.context)->draft = draft;
+
+ return (PyObject*) decoder;
+}
+#endif
diff --git a/Imaging/display.c b/Imaging/display.c
new file mode 100644
index 0000000..0c97ace
--- /dev/null
+++ b/Imaging/display.c
@@ -0,0 +1,731 @@
+/*
+ * The Python Imaging Library.
+ * $Id: display.c 2751 2006-06-18 19:50:45Z fredrik $
+ *
+ * display support
+ *
+ * History:
+ * 1996-05-13 fl Windows DIB support
+ * 1996-05-21 fl Added palette stuff
+ * 1996-05-28 fl Added display_mode stuff
+ * 1997-09-21 fl Added draw primitive
+ * 2001-09-17 fl Added ImagingGrabScreen (from _grabscreen.c)
+ * 2002-05-12 fl Added ImagingListWindows
+ * 2002-11-19 fl Added clipboard support
+ * 2002-11-25 fl Added GetDC/ReleaseDC helpers
+ * 2003-05-21 fl Added create window support (including window callback)
+ * 2003-09-05 fl Added fromstring/tostring methods
+ *
+ * Copyright (c) 1997-2003 by Secret Labs AB.
+ * Copyright (c) 1996-1997 by Fredrik Lundh.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Python.h"
+
+#if PY_VERSION_HEX < 0x01060000
+#define PyObject_New PyObject_NEW
+#define PyObject_Del PyMem_DEL
+#endif
+
+#include "Imaging.h"
+
+/* -------------------------------------------------------------------- */
+/* Windows DIB support */
+
+#ifdef WIN32
+
+#include "ImDib.h"
+
+typedef struct {
+ PyObject_HEAD
+ ImagingDIB dib;
+} ImagingDisplayObject;
+
+staticforward PyTypeObject ImagingDisplayType;
+
+static ImagingDisplayObject*
+_new(const char* mode, int xsize, int ysize)
+{
+ ImagingDisplayObject *display;
+
+ display = PyObject_New(ImagingDisplayObject, &ImagingDisplayType);
+ if (display == NULL)
+ return NULL;
+
+ display->dib = ImagingNewDIB(mode, xsize, ysize);
+ if (!display->dib) {
+ Py_DECREF(display);
+ return NULL;
+ }
+
+ return display;
+}
+
+static void
+_delete(ImagingDisplayObject* display)
+{
+ if (display->dib)
+ ImagingDeleteDIB(display->dib);
+ PyObject_Del(display);
+}
+
+static PyObject*
+_expose(ImagingDisplayObject* display, PyObject* args)
+{
+ int hdc;
+ if (!PyArg_ParseTuple(args, "i", &hdc))
+ return NULL;
+
+ ImagingExposeDIB(display->dib, hdc);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_draw(ImagingDisplayObject* display, PyObject* args)
+{
+ int hdc;
+ int dst[4];
+ int src[4];
+ if (!PyArg_ParseTuple(args, "i(iiii)(iiii)", &hdc,
+ dst+0, dst+1, dst+2, dst+3,
+ src+0, src+1, src+2, src+3))
+ return NULL;
+
+ ImagingDrawDIB(display->dib, hdc, dst, src);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+extern Imaging PyImaging_AsImaging(PyObject *op);
+
+static PyObject*
+_paste(ImagingDisplayObject* display, PyObject* args)
+{
+ Imaging im;
+
+ PyObject* op;
+ int xy[4];
+ xy[0] = xy[1] = xy[2] = xy[3] = 0;
+ if (!PyArg_ParseTuple(args, "O|(iiii)", &op, xy+0, xy+1, xy+2, xy+3))
+ return NULL;
+ im = PyImaging_AsImaging(op);
+ if (!im)
+ return NULL;
+
+ if (xy[2] <= xy[0])
+ xy[2] = xy[0] + im->xsize;
+ if (xy[3] <= xy[1])
+ xy[3] = xy[1] + im->ysize;
+
+ ImagingPasteDIB(display->dib, im, xy);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_query_palette(ImagingDisplayObject* display, PyObject* args)
+{
+ int hdc;
+ int status;
+
+ if (!PyArg_ParseTuple(args, "i", &hdc))
+ return NULL;
+
+ status = ImagingQueryPaletteDIB(display->dib, hdc);
+
+ return Py_BuildValue("i", status);
+}
+
+static PyObject*
+_getdc(ImagingDisplayObject* display, PyObject* args)
+{
+ int window;
+ HDC dc;
+
+ if (!PyArg_ParseTuple(args, "i", &window))
+ return NULL;
+
+ dc = GetDC((HWND) window);
+ if (!dc) {
+ PyErr_SetString(PyExc_IOError, "cannot create dc");
+ return NULL;
+ }
+
+ return Py_BuildValue("i", (int) dc);
+}
+
+static PyObject*
+_releasedc(ImagingDisplayObject* display, PyObject* args)
+{
+ int window, dc;
+
+ if (!PyArg_ParseTuple(args, "ii", &window, &dc))
+ return NULL;
+
+ ReleaseDC((HWND) window, (HDC) dc);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_fromstring(ImagingDisplayObject* display, PyObject* args)
+{
+ char* ptr;
+ int bytes;
+ if (!PyArg_ParseTuple(args, "s#:fromstring", &ptr, &bytes))
+ return NULL;
+
+ if (display->dib->ysize * display->dib->linesize != bytes) {
+ PyErr_SetString(PyExc_ValueError, "wrong size");
+ return NULL;
+ }
+
+ memcpy(display->dib->bits, ptr, bytes);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_tostring(ImagingDisplayObject* display, PyObject* args)
+{
+ if (!PyArg_ParseTuple(args, ":tostring"))
+ return NULL;
+
+ return PyString_FromStringAndSize(
+ display->dib->bits, display->dib->ysize * display->dib->linesize
+ );
+}
+
+static struct PyMethodDef methods[] = {
+ {"draw", (PyCFunction)_draw, 1},
+ {"expose", (PyCFunction)_expose, 1},
+ {"paste", (PyCFunction)_paste, 1},
+ {"query_palette", (PyCFunction)_query_palette, 1},
+ {"getdc", (PyCFunction)_getdc, 1},
+ {"releasedc", (PyCFunction)_releasedc, 1},
+ {"fromstring", (PyCFunction)_fromstring, 1},
+ {"tostring", (PyCFunction)_tostring, 1},
+ {NULL, NULL} /* sentinel */
+};
+
+static PyObject*
+_getattr(ImagingDisplayObject* self, char* name)
+{
+ PyObject* res;
+
+ res = Py_FindMethod(methods, (PyObject*) self, name);
+ if (res)
+ return res;
+ PyErr_Clear();
+ if (!strcmp(name, "mode"))
+ return Py_BuildValue("s", self->dib->mode);
+ if (!strcmp(name, "size"))
+ return Py_BuildValue("ii", self->dib->xsize, self->dib->ysize);
+ PyErr_SetString(PyExc_AttributeError, name);
+ return NULL;
+}
+
+statichere PyTypeObject ImagingDisplayType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "ImagingDisplay", /*tp_name*/
+ sizeof(ImagingDisplayObject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor)_delete, /*tp_dealloc*/
+ 0, /*tp_print*/
+ (getattrfunc)_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_hash*/
+};
+
+PyObject*
+PyImaging_DisplayWin32(PyObject* self, PyObject* args)
+{
+ ImagingDisplayObject* display;
+ char *mode;
+ int xsize, ysize;
+
+ if (!PyArg_ParseTuple(args, "s(ii)", &mode, &xsize, &ysize))
+ return NULL;
+
+ display = _new(mode, xsize, ysize);
+ if (display == NULL)
+ return NULL;
+
+ return (PyObject*) display;
+}
+
+PyObject*
+PyImaging_DisplayModeWin32(PyObject* self, PyObject* args)
+{
+ char *mode;
+ int size[2];
+
+ mode = ImagingGetModeDIB(size);
+
+ return Py_BuildValue("s(ii)", mode, size[0], size[1]);
+}
+
+/* -------------------------------------------------------------------- */
+/* Windows screen grabber */
+
+PyObject*
+PyImaging_GrabScreenWin32(PyObject* self, PyObject* args)
+{
+ int width, height;
+ HBITMAP bitmap;
+ BITMAPCOREHEADER core;
+ HDC screen, screen_copy;
+ PyObject* buffer;
+
+ /* step 1: create a memory DC large enough to hold the
+ entire screen */
+
+ screen = CreateDC("DISPLAY", NULL, NULL, NULL);
+ screen_copy = CreateCompatibleDC(screen);
+
+ width = GetDeviceCaps(screen, HORZRES);
+ height = GetDeviceCaps(screen, VERTRES);
+
+ bitmap = CreateCompatibleBitmap(screen, width, height);
+ if (!bitmap)
+ goto error;
+
+ if (!SelectObject(screen_copy, bitmap))
+ goto error;
+
+ /* step 2: copy bits into memory DC bitmap */
+
+ if (!BitBlt(screen_copy, 0, 0, width, height, screen, 0, 0, SRCCOPY))
+ goto error;
+
+ /* step 3: extract bits from bitmap */
+
+ buffer = PyString_FromStringAndSize(NULL, height * ((width*3 + 3) & -4));
+ if (!buffer)
+ return NULL;
+
+ core.bcSize = sizeof(core);
+ core.bcWidth = width;
+ core.bcHeight = height;
+ core.bcPlanes = 1;
+ core.bcBitCount = 24;
+ if (!GetDIBits(screen_copy, bitmap, 0, height, PyString_AS_STRING(buffer),
+ (BITMAPINFO*) &core, DIB_RGB_COLORS))
+ goto error;
+
+ DeleteObject(bitmap);
+ DeleteDC(screen_copy);
+ DeleteDC(screen);
+
+ return Py_BuildValue("(ii)N", width, height, buffer);
+
+error:
+ PyErr_SetString(PyExc_IOError, "screen grab failed");
+
+ DeleteDC(screen_copy);
+ DeleteDC(screen);
+
+ return NULL;
+}
+
+static BOOL CALLBACK list_windows_callback(HWND hwnd, LPARAM lParam)
+{
+ PyObject* window_list = (PyObject*) lParam;
+ PyObject* item;
+ PyObject* title;
+ RECT inner, outer;
+ int title_size;
+ int status;
+
+ /* get window title */
+ title_size = GetWindowTextLength(hwnd);
+ if (title_size > 0) {
+ title = PyString_FromStringAndSize(NULL, title_size);
+ if (title)
+ GetWindowText(hwnd, PyString_AS_STRING(title), title_size+1);
+ } else
+ title = PyString_FromString("");
+ if (!title)
+ return 0;
+
+ /* get bounding boxes */
+ GetClientRect(hwnd, &inner);
+ GetWindowRect(hwnd, &outer);
+
+ item = Py_BuildValue(
+ "lN(iiii)(iiii)", (long) hwnd, title,
+ inner.left, inner.top, inner.right, inner.bottom,
+ outer.left, outer.top, outer.right, outer.bottom
+ );
+ if (!item)
+ return 0;
+
+ status = PyList_Append(window_list, item);
+
+ Py_DECREF(item);
+
+ if (status < 0)
+ return 0;
+
+ return 1;
+}
+
+PyObject*
+PyImaging_ListWindowsWin32(PyObject* self, PyObject* args)
+{
+ PyObject* window_list;
+
+ window_list = PyList_New(0);
+ if (!window_list)
+ return NULL;
+
+ EnumWindows(list_windows_callback, (LPARAM) window_list);
+
+ if (PyErr_Occurred()) {
+ Py_DECREF(window_list);
+ return NULL;
+ }
+
+ return window_list;
+}
+
+/* -------------------------------------------------------------------- */
+/* Windows clipboard grabber */
+
+PyObject*
+PyImaging_GrabClipboardWin32(PyObject* self, PyObject* args)
+{
+ int clip;
+ HANDLE handle;
+ int size;
+ void* data;
+ PyObject* result;
+
+ int verbose = 0; /* debugging; will be removed in future versions */
+ if (!PyArg_ParseTuple(args, "|i", &verbose))
+ return NULL;
+
+
+ clip = OpenClipboard(NULL);
+ /* FIXME: check error status */
+
+ if (verbose) {
+ UINT format = EnumClipboardFormats(0);
+ char buffer[200];
+ char* result;
+ while (format != 0) {
+ if (GetClipboardFormatName(format, buffer, sizeof buffer) > 0)
+ result = buffer;
+ else
+ switch (format) {
+ case CF_BITMAP:
+ result = "CF_BITMAP";
+ break;
+ case CF_DIB:
+ result = "CF_DIB";
+ break;
+ case CF_DIF:
+ result = "CF_DIF";
+ break;
+ case CF_ENHMETAFILE:
+ result = "CF_ENHMETAFILE";
+ break;
+ case CF_HDROP:
+ result = "CF_HDROP";
+ break;
+ case CF_LOCALE:
+ result = "CF_LOCALE";
+ break;
+ case CF_METAFILEPICT:
+ result = "CF_METAFILEPICT";
+ break;
+ case CF_OEMTEXT:
+ result = "CF_OEMTEXT";
+ break;
+ case CF_OWNERDISPLAY:
+ result = "CF_OWNERDISPLAY";
+ break;
+ case CF_PALETTE:
+ result = "CF_PALETTE";
+ break;
+ case CF_PENDATA:
+ result = "CF_PENDATA";
+ break;
+ case CF_RIFF:
+ result = "CF_RIFF";
+ break;
+ case CF_SYLK:
+ result = "CF_SYLK";
+ break;
+ case CF_TEXT:
+ result = "CF_TEXT";
+ break;
+ case CF_WAVE:
+ result = "CF_WAVE";
+ break;
+ case CF_TIFF:
+ result = "CF_TIFF";
+ break;
+ case CF_UNICODETEXT:
+ result = "CF_UNICODETEXT";
+ break;
+ default:
+ sprintf(buffer, "[%d]", format);
+ result = buffer;
+ break;
+ }
+ printf("%s (%d)\n", result, format);
+ format = EnumClipboardFormats(format);
+ }
+ }
+
+ handle = GetClipboardData(CF_DIB);
+ if (!handle) {
+ /* FIXME: add CF_HDROP support to allow cut-and-paste from
+ the explorer */
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ size = GlobalSize(handle);
+ data = GlobalLock(handle);
+
+#if 0
+ /* calculate proper size for string formats */
+ if (format == CF_TEXT || format == CF_OEMTEXT)
+ size = strlen(data);
+ else if (format == CF_UNICODETEXT)
+ size = wcslen(data) * 2;
+#endif
+
+ result = PyString_FromStringAndSize(data, size);
+
+ GlobalUnlock(handle);
+
+ CloseClipboard();
+
+ return result;
+}
+
+/* -------------------------------------------------------------------- */
+/* Windows class */
+
+#ifndef WM_MOUSEWHEEL
+#define WM_MOUSEWHEEL 522
+#endif
+
+static int mainloop = 0;
+
+static void
+callback_error(const char* handler)
+{
+ PyObject* sys_stderr;
+
+ sys_stderr = PySys_GetObject("stderr");
+
+ if (sys_stderr) {
+ PyFile_WriteString("*** ImageWin: error in ", sys_stderr);
+ PyFile_WriteString((char*) handler, sys_stderr);
+ PyFile_WriteString(":\n", sys_stderr);
+ }
+
+ PyErr_Print();
+ PyErr_Clear();
+}
+
+static LRESULT CALLBACK
+windowCallback(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ PAINTSTRUCT ps;
+ PyObject* callback = NULL;
+ PyObject* result;
+ PyThreadState* threadstate;
+ PyThreadState* current_threadstate;
+ HDC dc;
+ RECT rect;
+ LRESULT status = 0;
+
+ /* set up threadstate for messages that calls back into python */
+ switch (message) {
+ case WM_CREATE:
+ mainloop++;
+ break;
+ case WM_DESTROY:
+ mainloop--;
+ /* fall through... */
+ case WM_PAINT:
+ case WM_SIZE:
+ callback = (PyObject*) GetWindowLong(wnd, 0);
+ if (callback) {
+ threadstate = (PyThreadState*)
+ GetWindowLong(wnd, sizeof(PyObject*));
+ current_threadstate = PyThreadState_Swap(NULL);
+ PyEval_RestoreThread(threadstate);
+ } else
+ return DefWindowProc(wnd, message, wParam, lParam);
+ }
+
+ /* process message */
+ switch (message) {
+
+ case WM_PAINT:
+ /* redraw (part of) window. this generates a WCK-style
+ damage/clear/repair cascade */
+ BeginPaint(wnd, &ps);
+ dc = GetDC(wnd);
+ GetWindowRect(wnd, &rect); /* in screen coordinates */
+
+ result = PyObject_CallFunction(
+ callback, "siiii", "damage",
+ ps.rcPaint.left, ps.rcPaint.top,
+ ps.rcPaint.right, ps.rcPaint.bottom
+ );
+ if (result)
+ Py_DECREF(result);
+ else
+ callback_error("window damage callback");
+
+ result = PyObject_CallFunction(
+ callback, "siiiii", "clear", (int) dc,
+ 0, 0, rect.right-rect.left, rect.bottom-rect.top
+ );
+ if (result)
+ Py_DECREF(result);
+ else
+ callback_error("window clear callback");
+
+ result = PyObject_CallFunction(
+ callback, "siiiii", "repair", (int) dc,
+ 0, 0, rect.right-rect.left, rect.bottom-rect.top
+ );
+ if (result)
+ Py_DECREF(result);
+ else
+ callback_error("window repair callback");
+
+ ReleaseDC(wnd, dc);
+ EndPaint(wnd, &ps);
+ break;
+
+ case WM_SIZE:
+ /* resize window */
+ result = PyObject_CallFunction(
+ callback, "sii", "resize", LOWORD(lParam), HIWORD(lParam)
+ );
+ if (result) {
+ InvalidateRect(wnd, NULL, 1);
+ Py_DECREF(result);
+ } else
+ callback_error("window resize callback");
+ break;
+
+ case WM_DESTROY:
+ /* destroy window */
+ result = PyObject_CallFunction(callback, "s", "destroy");
+ if (result)
+ Py_DECREF(result);
+ else
+ callback_error("window destroy callback");
+ Py_DECREF(callback);
+ break;
+
+ default:
+ status = DefWindowProc(wnd, message, wParam, lParam);
+ }
+
+ if (callback) {
+ /* restore thread state */
+ PyEval_SaveThread();
+ PyThreadState_Swap(threadstate);
+ }
+
+ return status;
+}
+
+PyObject*
+PyImaging_CreateWindowWin32(PyObject* self, PyObject* args)
+{
+ HWND wnd;
+ WNDCLASS windowClass;
+
+ char* title;
+ PyObject* callback;
+ int width = 0, height = 0;
+ if (!PyArg_ParseTuple(args, "sO|ii", &title, &callback, &width, &height))
+ return NULL;
+
+ if (width <= 0)
+ width = CW_USEDEFAULT;
+ if (height <= 0)
+ height = CW_USEDEFAULT;
+
+ /* register toplevel window class */
+ windowClass.style = CS_CLASSDC;
+ windowClass.cbClsExtra = 0;
+ windowClass.cbWndExtra = sizeof(PyObject*) + sizeof(PyThreadState*);
+ windowClass.hInstance = GetModuleHandle(NULL);
+ /* windowClass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); */
+ windowClass.hbrBackground = NULL;
+ windowClass.lpszMenuName = NULL;
+ windowClass.lpszClassName = "pilWindow";
+ windowClass.lpfnWndProc = windowCallback;
+ windowClass.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(1));
+ windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); /* CROSS? */
+
+ RegisterClass(&windowClass); /* FIXME: check return status */
+
+ wnd = CreateWindowEx(
+ 0, windowClass.lpszClassName, title,
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, width, height,
+ HWND_DESKTOP, NULL, NULL, NULL
+ );
+
+ if (!wnd) {
+ PyErr_SetString(PyExc_IOError, "failed to create window");
+ return NULL;
+ }
+
+ /* register window callback */
+ Py_INCREF(callback);
+ SetWindowLong(wnd, 0, (LONG) callback);
+ SetWindowLong(wnd, sizeof(callback), (LONG) PyThreadState_Get());
+
+ Py_BEGIN_ALLOW_THREADS
+ ShowWindow(wnd, SW_SHOWNORMAL);
+ SetForegroundWindow(wnd); /* to make sure it's visible */
+ Py_END_ALLOW_THREADS
+
+ return Py_BuildValue("l", (long) wnd);
+}
+
+PyObject*
+PyImaging_EventLoopWin32(PyObject* self, PyObject* args)
+{
+ MSG msg;
+
+ Py_BEGIN_ALLOW_THREADS
+ while (mainloop && GetMessage(&msg, NULL, 0, 0)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ Py_END_ALLOW_THREADS
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+#endif /* WIN32 */
diff --git a/Imaging/doctest.py b/Imaging/doctest.py
new file mode 100644
index 0000000..e8140ec
--- /dev/null
+++ b/Imaging/doctest.py
@@ -0,0 +1,1111 @@
+# Module doctest version 0.9.6
+# Released to the public domain 16-Jan-2001,
+# by Tim Peters (tim.one@home.com).
+
+# local modifications:
+# 2001-02-13 fl: minor tweaks to make it run under both 1.5.2 and 2.0
+
+# Provided as-is; use at your own risk; no warranty; no promises; enjoy!
+
+"""Module doctest -- a framework for running examples in docstrings.
+
+NORMAL USAGE
+
+In normal use, end each module M with:
+
+def _test():
+ import doctest, M # replace M with your module's name
+ return doctest.testmod(M) # ditto
+
+if __name__ == "__main__":
+ _test()
+
+Then running the module as a script will cause the examples in the
+docstrings to get executed and verified:
+
+python M.py
+
+This won't display anything unless an example fails, in which case the
+failing example(s) and the cause(s) of the failure(s) are printed to stdout
+(why not stderr? because stderr is a lame hack <0.2 wink>), and the final
+line of output is "Test failed.".
+
+Run it with the -v switch instead:
+
+python M.py -v
+
+and a detailed report of all examples tried is printed to stdout, along
+with assorted summaries at the end.
+
+You can force verbose mode by passing "verbose=1" to testmod, or prohibit
+it by passing "verbose=0". In either of those cases, sys.argv is not
+examined by testmod.
+
+In any case, testmod returns a 2-tuple of ints (f, t), where f is the
+number of docstring examples that failed and t is the total number of
+docstring examples attempted.
+
+
+WHICH DOCSTRINGS ARE EXAMINED?
+
++ M.__doc__.
+
++ f.__doc__ for all functions f in M.__dict__.values(), except those
+ with private names.
+
++ C.__doc__ for all classes C in M.__dict__.values(), except those with
+ private names.
+
++ If M.__test__ exists and "is true", it must be a dict, and
+ each entry maps a (string) name to a function object, class object, or
+ string. Function and class object docstrings found from M.__test__
+ are searched even if the name is private, and strings are searched
+ directly as if they were docstrings. In output, a key K in M.__test__
+ appears with name
+ <name of M>.__test__.K
+
+Any classes found are recursively searched similarly, to test docstrings in
+their contained methods and nested classes. Private names reached from M's
+globals are skipped, but all names reached from M.__test__ are searched.
+
+By default, a name is considered to be private if it begins with an
+underscore (like "_my_func") but doesn't both begin and end with (at least)
+two underscores (like "__init__"). You can change the default by passing
+your own "isprivate" function to testmod.
+
+If you want to test docstrings in objects with private names too, stuff
+them into an M.__test__ dict, or see ADVANCED USAGE below (e.g., pass your
+own isprivate function to Tester's constructor, or call the rundoc method
+of a Tester instance).
+
+Warning: imports can cause trouble; e.g., if you do
+
+from XYZ import XYZclass
+
+then XYZclass is a name in M.__dict__ too, and doctest has no way to know
+that XYZclass wasn't *defined* in M. So it may try to execute the examples
+in XYZclass's docstring, and those in turn may require a different set of
+globals to work correctly. I prefer to do "import *"- friendly imports,
+a la
+
+import XYY
+_XYZclass = XYZ.XYZclass
+del XYZ
+
+or (Python 2.0)
+
+from XYZ import XYZclass as _XYZclass
+
+and then the leading underscore stops testmod from going nuts. You may
+prefer the method in the next section.
+
+
+WHAT'S THE EXECUTION CONTEXT?
+
+By default, each time testmod finds a docstring to test, it uses a *copy*
+of M's globals (so that running tests on a module doesn't change the
+module's real globals, and so that one test in M can't leave behind crumbs
+that accidentally allow another test to work). This means examples can
+freely use any names defined at top-level in M. It also means that sloppy
+imports (see above) can cause examples in external docstrings to use
+globals inappropriate for them.
+
+You can force use of your own dict as the execution context by passing
+"globs=your_dict" to testmod instead. Presumably this would be a copy of
+M.__dict__ merged with the globals from other imported modules.
+
+
+WHAT IF I WANT TO TEST A WHOLE PACKAGE?
+
+Piece o' cake, provided the modules do their testing from docstrings.
+Here's the test.py I use for the world's most elaborate Rational/
+floating-base-conversion pkg (which I'll distribute some day):
+
+from Rational import Cvt
+from Rational import Format
+from Rational import machprec
+from Rational import Rat
+from Rational import Round
+from Rational import utils
+
+modules = (Cvt,
+ Format,
+ machprec,
+ Rat,
+ Round,
+ utils)
+
+def _test():
+ import doctest
+ import sys
+ verbose = "-v" in sys.argv
+ for mod in modules:
+ doctest.testmod(mod, verbose=verbose, report=0)
+ doctest.master.summarize()
+
+if __name__ == "__main__":
+ _test()
+
+IOW, it just runs testmod on all the pkg modules. testmod remembers the
+names and outcomes (# of failures, # of tries) for each item it's seen, and
+passing "report=0" prevents it from printing a summary in verbose mode.
+Instead, the summary is delayed until all modules have been tested, and
+then "doctest.master.summarize()" forces the summary at the end.
+
+So this is very nice in practice: each module can be tested individually
+with almost no work beyond writing up docstring examples, and collections
+of modules can be tested too as a unit with no more work than the above.
+
+
+WHAT ABOUT EXCEPTIONS?
+
+No problem, as long as the only output generated by the example is the
+traceback itself. For example:
+
+ >>> a = [None]
+ >>> a[1]
+ Traceback (innermost last):
+ File "<stdin>", line 1, in ?
+ IndexError: list index out of range
+ >>>
+
+Note that only the exception type and value are compared (specifically,
+only the last line in the traceback).
+
+
+ADVANCED USAGE
+
+doctest.testmod() captures the testing policy I find most useful most
+often. You may want other policies.
+
+testmod() actually creates a local instance of class doctest.Tester, runs
+appropriate methods of that class, and merges the results into global
+Tester instance doctest.master.
+
+You can create your own instances of doctest.Tester, and so build your own
+policies, or even run methods of doctest.master directly. See
+doctest.Tester.__doc__ for details.
+
+
+SO WHAT DOES A DOCSTRING EXAMPLE LOOK LIKE ALREADY!?
+
+Oh ya. It's easy! In most cases a copy-and-paste of an interactive
+console session works fine -- just make sure the leading whitespace is
+rigidly consistent (you can mix tabs and spaces if you're too lazy to do it
+right, but doctest is not in the business of guessing what you think a tab
+means).
+
+ >>> # comments are ignored
+ >>> x = 12
+ >>> x
+ 12
+ >>> if x == 13:
+ ... print "yes"
+ ... else:
+ ... print "no"
+ ... print "NO"
+ ... print "NO!!!"
+ ...
+ no
+ NO
+ NO!!!
+ >>>
+
+Any expected output must immediately follow the final ">>>" or "..." line
+containing the code, and the expected output (if any) extends to the next
+">>>" or all-whitespace line. That's it.
+
+Bummers:
+
++ Expected output cannot contain an all-whitespace line, since such a line
+ is taken to signal the end of expected output.
+
++ Output to stdout is captured, but not output to stderr (exception
+ tracebacks are captured via a different means).
+
++ If you continue a line via backslashing in an interactive session, or for
+ any other reason use a backslash, you need to double the backslash in the
+ docstring version. This is simply because you're in a string, and so the
+ backslash must be escaped for it to survive intact. Like:
+
+>>> if "yes" == \\
+... "y" + \\
+... "es": # in the source code you'll see the doubled backslashes
+... print 'yes'
+yes
+
+The starting column doesn't matter:
+
+>>> assert "Easy!"
+ >>> import math
+ >>> math.floor(1.9)
+ 1.0
+
+and as many leading whitespace characters are stripped from the expected
+output as appeared in the initial ">>>" line that triggered it.
+
+If you execute this very file, the examples above will be found and
+executed, leading to this output in verbose mode:
+
+Running doctest.__doc__
+Trying: a = [None]
+Expecting: nothing
+ok
+Trying: a[1]
+Expecting:
+Traceback (innermost last):
+ File "<stdin>", line 1, in ?
+IndexError: list index out of range
+ok
+Trying: x = 12
+Expecting: nothing
+ok
+Trying: x
+Expecting: 12
+ok
+Trying:
+if x == 13:
+ print "yes"
+else:
+ print "no"
+ print "NO"
+ print "NO!!!"
+Expecting:
+no
+NO
+NO!!!
+ok
+... and a bunch more like that, with this summary at the end:
+
+5 items had no tests:
+ doctest.Tester.__init__
+ doctest.Tester.run__test__
+ doctest.Tester.summarize
+ doctest.run_docstring_examples
+ doctest.testmod
+12 items passed all tests:
+ 9 tests in doctest
+ 6 tests in doctest.Tester
+ 10 tests in doctest.Tester.merge
+ 7 tests in doctest.Tester.rundict
+ 3 tests in doctest.Tester.rundoc
+ 3 tests in doctest.Tester.runstring
+ 2 tests in doctest.__test__._TestClass
+ 2 tests in doctest.__test__._TestClass.__init__
+ 2 tests in doctest.__test__._TestClass.get
+ 1 tests in doctest.__test__._TestClass.square
+ 2 tests in doctest.__test__.string
+ 7 tests in doctest.is_private
+54 tests in 17 items.
+54 passed and 0 failed.
+Test passed.
+"""
+
+# 0,0,1 06-Mar-1999
+# initial version posted
+# 0,0,2 06-Mar-1999
+# loosened parsing:
+# cater to stinkin' tabs
+# don't insist on a blank after PS2 prefix
+# so trailing "... " line from a compound stmt no longer
+# breaks if the file gets whitespace-trimmed
+# better error msgs for inconsistent leading whitespace
+# 0,9,1 08-Mar-1999
+# exposed the Tester class and added client methods
+# plus docstring examples of their use (eww - head-twisting!)
+# fixed logic error in reporting total # of tests & failures
+# added __test__ support to testmod (a pale reflection of Christian
+# Tismer's vision ...)
+# removed the "deep" argument; fiddle __test__ instead
+# simplified endcase logic for extracting tests, and running them.
+# before, if no output was expected but some was produced
+# anyway via an eval'ed result, the discrepancy wasn't caught
+# made TestClass private and used __test__ to get at it
+# many doc updates
+# speed _SpoofOut for long expected outputs
+# 0,9,2 09-Mar-1999
+# throw out comments from examples, enabling use of the much simpler
+# exec compile(... "single") ...
+# for simulating the runtime; that barfs on comment-only lines
+# used the traceback module to do a much better job of reporting
+# exceptions
+# run __doc__ values thru str(), "just in case"
+# privateness of names now determined by an overridable "isprivate"
+# function
+# by default a name now considered to be private iff it begins with
+# an underscore but doesn't both begin & end with two of 'em; so
+# e.g. Class.__init__ etc are searched now -- as they always
+# should have been
+# 0,9,3 18-Mar-1999
+# added .flush stub to _SpoofOut (JPython buglet diagnosed by
+# Hugh Emberson)
+# repaired ridiculous docs about backslashes in examples
+# minor internal changes
+# changed source to Unix line-end conventions
+# moved __test__ logic into new Tester.run__test__ method
+# 0,9,4 27-Mar-1999
+# report item name and line # in failing examples
+# 0,9,5 29-Jun-1999
+# allow straightforward exceptions in examples - thanks to Mark Hammond!
+# 0,9,6 16-Jan-2001
+# fiddling for changes in Python 2.0: some of the embedded docstring
+# examples no longer worked *exactly* as advertised, due to minor
+# language changes, and running doctest on itself pointed that out.
+# Hard to think of a better example of why this is useful <wink>.
+
+__version__ = 0, 9, 6
+
+import types
+_FunctionType = types.FunctionType
+_ClassType = types.ClassType
+_ModuleType = types.ModuleType
+_StringType = types.StringType
+del types
+
+import string
+_string_find = string.find
+_string_join = string.join
+_string_split = string.split
+_string_rindex = string.rindex
+del string
+
+import re
+PS1 = ">>>"
+PS2 = "..."
+_isPS1 = re.compile(r"(\s*)" + re.escape(PS1)).match
+_isPS2 = re.compile(r"(\s*)" + re.escape(PS2)).match
+_isEmpty = re.compile(r"\s*$").match
+_isComment = re.compile(r"\s*#").match
+del re
+
+__all__ = []
+
+# Extract interactive examples from a string. Return a list of triples,
+# (source, outcome, lineno). "source" is the source code, and ends
+# with a newline iff the source spans more than one line. "outcome" is
+# the expected output if any, else an empty string. When not empty,
+# outcome always ends with a newline. "lineno" is the line number,
+# 0-based wrt the start of the string, of the first source line.
+
+def _extract_examples(s):
+ isPS1, isPS2 = _isPS1, _isPS2
+ isEmpty, isComment = _isEmpty, _isComment
+ examples = []
+ lines = _string_split(s, "\n")
+ i, n = 0, len(lines)
+ while i < n:
+ line = lines[i]
+ i = i + 1
+ m = isPS1(line)
+ if m is None:
+ continue
+ j = m.end(0) # beyond the prompt
+ if isEmpty(line, j) or isComment(line, j):
+ # a bare prompt or comment -- not interesting
+ continue
+ lineno = i - 1
+ if line[j] != " ":
+ raise ValueError("line " + `lineno` + " of docstring lacks "
+ "blank after " + PS1 + ": " + line)
+ j = j + 1
+ blanks = m.group(1)
+ nblanks = len(blanks)
+ # suck up this and following PS2 lines
+ source = []
+ while 1:
+ source.append(line[j:])
+ line = lines[i]
+ m = isPS2(line)
+ if m:
+ if m.group(1) != blanks:
+ raise ValueError("inconsistent leading whitespace "
+ "in line " + `i` + " of docstring: " + line)
+ i = i + 1
+ else:
+ break
+ if len(source) == 1:
+ source = source[0]
+ else:
+ # get rid of useless null line from trailing empty "..."
+ if source[-1] == "":
+ del source[-1]
+ source = _string_join(source, "\n") + "\n"
+ # suck up response
+ if isPS1(line) or isEmpty(line):
+ expect = ""
+ else:
+ expect = []
+ while 1:
+ if line[:nblanks] != blanks:
+ raise ValueError("inconsistent leading whitespace "
+ "in line " + `i` + " of docstring: " + line)
+ expect.append(line[nblanks:])
+ i = i + 1
+ line = lines[i]
+ if isPS1(line) or isEmpty(line):
+ break
+ expect = _string_join(expect, "\n") + "\n"
+ examples.append( (source, expect, lineno) )
+ return examples
+
+# Capture stdout when running examples.
+
+class _SpoofOut:
+ def __init__(self):
+ self.clear()
+ def write(self, s):
+ self.buf.append(s)
+ def get(self):
+ return _string_join(self.buf, "")
+ def clear(self):
+ self.buf = []
+ def flush(self):
+ # JPython calls flush
+ pass
+
+# Display some tag-and-msg pairs nicely, keeping the tag and its msg
+# on the same line when that makes sense.
+
+def _tag_out(printer, *tag_msg_pairs):
+ for tag, msg in tag_msg_pairs:
+ printer(tag + ":")
+ msg_has_nl = msg[-1:] == "\n"
+ msg_has_two_nl = msg_has_nl and \
+ _string_find(msg, "\n") < len(msg) - 1
+ if len(tag) + len(msg) < 76 and not msg_has_two_nl:
+ printer(" ")
+ else:
+ printer("\n")
+ printer(msg)
+ if not msg_has_nl:
+ printer("\n")
+
+# Run list of examples, in context globs. "out" can be used to display
+# stuff to "the real" stdout, and fakeout is an instance of _SpoofOut
+# that captures the examples' std output. Return (#failures, #tries).
+
+def _run_examples_inner(out, fakeout, examples, globs, verbose, name):
+ import sys, traceback
+ OK, BOOM, FAIL = range(3)
+ NADA = "nothing"
+ stderr = _SpoofOut()
+ failures = 0
+ for source, want, lineno in examples:
+ if verbose:
+ _tag_out(out, ("Trying", source),
+ ("Expecting", want or NADA))
+ fakeout.clear()
+ try:
+ exec compile(source, "<string>", "single") in globs
+ got = fakeout.get()
+ state = OK
+ except:
+ # See whether the exception was expected.
+ if _string_find(want, "Traceback (innermost last):\n") == 0 or\
+ _string_find(want, "Traceback (most recent call last):\n") == 0:
+ # Only compare exception type and value - the rest of
+ # the traceback isn't necessary.
+ want = _string_split(want, '\n')[-2] + '\n'
+ exc_type, exc_val, exc_tb = sys.exc_info()
+ got = traceback.format_exception_only(exc_type, exc_val)[0]
+ state = OK
+ else:
+ # unexpected exception
+ stderr.clear()
+ traceback.print_exc(file=stderr)
+ state = BOOM
+
+ if state == OK:
+ if got == want:
+ if verbose:
+ out("ok\n")
+ continue
+ state = FAIL
+
+ assert state in (FAIL, BOOM)
+ failures = failures + 1
+ out("*" * 65 + "\n")
+ _tag_out(out, ("Failure in example", source))
+ out("from line #" + `lineno` + " of " + name + "\n")
+ if state == FAIL:
+ _tag_out(out, ("Expected", want or NADA), ("Got", got))
+ else:
+ assert state == BOOM
+ _tag_out(out, ("Exception raised", stderr.get()))
+
+ return failures, len(examples)
+
+# Run list of examples, in context globs. Return (#failures, #tries).
+
+def _run_examples(examples, globs, verbose, name):
+ import sys
+ saveout = sys.stdout
+ try:
+ sys.stdout = fakeout = _SpoofOut()
+ x = _run_examples_inner(saveout.write, fakeout, examples,
+ globs, verbose, name)
+ finally:
+ sys.stdout = saveout
+ return x
+
+def run_docstring_examples(f, globs, verbose=0, name="NoName"):
+ """f, globs, verbose=0, name="NoName" -> run examples from f.__doc__.
+
+ Use dict globs as the globals for execution.
+ Return (#failures, #tries).
+
+ If optional arg verbose is true, print stuff even if there are no
+ failures.
+ Use string name in failure msgs.
+ """
+
+ try:
+ doc = f.__doc__
+ if not doc:
+ # docstring empty or None
+ return 0, 0
+ # just in case CT invents a doc object that has to be forced
+ # to look like a string <0.9 wink>
+ doc = str(doc)
+ except:
+ return 0, 0
+
+ e = _extract_examples(doc)
+ if not e:
+ return 0, 0
+ return _run_examples(e, globs, verbose, name)
+
+def is_private(prefix, base):
+ """prefix, base -> true iff name prefix + "." + base is "private".
+
+ Prefix may be an empty string, and base does not contain a period.
+ Prefix is ignored (although functions you write conforming to this
+ protocol may make use of it).
+ Return true iff base begins with an (at least one) underscore, but
+ does not both begin and end with (at least) two underscores.
+
+ >>> is_private("a.b", "my_func")
+ 0
+ >>> is_private("____", "_my_func")
+ 1
+ >>> is_private("someclass", "__init__")
+ 0
+ >>> is_private("sometypo", "__init_")
+ 1
+ >>> is_private("x.y.z", "_")
+ 1
+ >>> is_private("_x.y.z", "__")
+ 0
+ >>> is_private("", "") # senseless but consistent
+ 0
+ """
+
+ return base[:1] == "_" and not base[:2] == "__" == base[-2:]
+
+class Tester:
+ """Class Tester -- runs docstring examples and accumulates stats.
+
+In normal use, function doctest.testmod() hides all this from you,
+so use that if you can. Create your own instances of Tester to do
+fancier things.
+
+Methods:
+ runstring(s, name)
+ Search string s for examples to run; use name for logging.
+ Return (#failures, #tries).
+
+ rundoc(object, name=None)
+ Search object.__doc__ for examples to run; use name (or
+ object.__name__) for logging. Return (#failures, #tries).
+
+ rundict(d, name)
+ Search for examples in docstrings in all of d.values(); use name
+ for logging. Return (#failures, #tries).
+
+ run__test__(d, name)
+ Treat dict d like module.__test__. Return (#failures, #tries).
+
+ summarize(verbose=None)
+ Display summary of testing results, to stdout. Return
+ (#failures, #tries).
+
+ merge(other)
+ Merge in the test results from Tester instance "other".
+
+>>> from doctest import Tester
+>>> t = Tester(globs={'x': 42}, verbose=0)
+>>> t.runstring(r'''
+... >>> x = x * 2
+... >>> print x
+... 42
+... ''', 'XYZ')
+*****************************************************************
+Failure in example: print x
+from line #2 of XYZ
+Expected: 42
+Got: 84
+(1, 2)
+>>> t.runstring(">>> x = x * 2\\n>>> print x\\n84\\n", 'example2')
+(0, 2)
+>>> t.summarize()
+1 items had failures:
+ 1 of 2 in XYZ
+***Test Failed*** 1 failures.
+(1, 4)
+>>> t.summarize(verbose=1)
+1 items passed all tests:
+ 2 tests in example2
+1 items had failures:
+ 1 of 2 in XYZ
+4 tests in 2 items.
+3 passed and 1 failed.
+***Test Failed*** 1 failures.
+(1, 4)
+>>>
+"""
+
+ def __init__(self, mod=None, globs=None, verbose=None,
+ isprivate=None):
+ """mod=None, globs=None, verbose=None, isprivate=None
+
+See doctest.__doc__ for an overview.
+
+Optional keyword arg "mod" is a module, whose globals are used for
+executing examples. If not specified, globs must be specified.
+
+Optional keyword arg "globs" gives a dict to be used as the globals
+when executing examples; if not specified, use the globals from
+module mod.
+
+In either case, a copy of the dict is used for each docstring
+examined.
+
+Optional keyword arg "verbose" prints lots of stuff if true, only
+failures if false; by default, it's true iff "-v" is in sys.argv.
+
+Optional keyword arg "isprivate" specifies a function used to determine
+whether a name is private. The default function is doctest.is_private;
+see its docs for details.
+"""
+
+ if mod is None and globs is None:
+ raise TypeError("Tester.__init__: must specify mod or globs")
+ if mod is not None and type(mod) is not _ModuleType:
+ raise TypeError("Tester.__init__: mod must be a module; " +
+ `mod`)
+ if globs is None:
+ globs = mod.__dict__
+ self.globs = globs
+
+ if verbose is None:
+ import sys
+ verbose = "-v" in sys.argv
+ self.verbose = verbose
+
+ if isprivate is None:
+ isprivate = is_private
+ self.isprivate = isprivate
+
+ self.name2ft = {} # map name to (#failures, #trials) pair
+
+ def runstring(self, s, name):
+ """
+ s, name -> search string s for examples to run, logging as name.
+
+ Use string name as the key for logging the outcome.
+ Return (#failures, #examples).
+
+ >>> t = Tester(globs={}, verbose=1)
+ >>> test = r'''
+ ... # just an example
+ ... >>> x = 1 + 2
+ ... >>> x
+ ... 3
+ ... '''
+ >>> t.runstring(test, "Example")
+ Running string Example
+ Trying: x = 1 + 2
+ Expecting: nothing
+ ok
+ Trying: x
+ Expecting: 3
+ ok
+ 0 of 2 examples failed in string Example
+ (0, 2)
+ """
+
+ if self.verbose:
+ print "Running string", name
+ f = t = 0
+ e = _extract_examples(s)
+ if e:
+ f, t = _run_examples(e, self.globs.copy(), self.verbose, name)
+ if self.verbose:
+ print f, "of", t, "examples failed in string", name
+ self.__record_outcome(name, f, t)
+ return f, t
+
+ def rundoc(self, object, name=None):
+ """
+ object, name=None -> search object.__doc__ for examples to run.
+
+ Use optional string name as the key for logging the outcome;
+ by default use object.__name__.
+ Return (#failures, #examples).
+ If object is a class object, search recursively for method
+ docstrings too.
+ object.__doc__ is examined regardless of name, but if object is
+ a class, whether private names reached from object are searched
+ depends on the constructor's "isprivate" argument.
+
+ >>> t = Tester(globs={}, verbose=0)
+ >>> def _f():
+ ... '''Trivial docstring example.
+ ... >>> assert 2 == 2
+ ... '''
+ ... return 32
+ ...
+ >>> t.rundoc(_f) # expect 0 failures in 1 example
+ (0, 1)
+ """
+
+ if name is None:
+ try:
+ name = object.__name__
+ except AttributeError:
+ raise ValueError("Tester.rundoc: name must be given "
+ "when object.__name__ doesn't exist; " + `object`)
+ if self.verbose:
+ print "Running", name + ".__doc__"
+ f, t = run_docstring_examples(object, self.globs.copy(),
+ self.verbose, name)
+ if self.verbose:
+ print f, "of", t, "examples failed in", name + ".__doc__"
+ self.__record_outcome(name, f, t)
+ if type(object) is _ClassType:
+ f2, t2 = self.rundict(object.__dict__, name)
+ f = f + f2
+ t = t + t2
+ return f, t
+
+ def rundict(self, d, name):
+ """
+ d. name -> search for docstring examples in all of d.values().
+
+ For k, v in d.items() such that v is a function or class,
+ do self.rundoc(v, name + "." + k). Whether this includes
+ objects with private names depends on the constructor's
+ "isprivate" argument.
+ Return aggregate (#failures, #examples).
+
+ >>> def _f():
+ ... '''>>> assert 1 == 1
+ ... '''
+ >>> def g():
+ ... '''>>> assert 2 != 1
+ ... '''
+ >>> d = {"_f": _f, "g": g}
+ >>> t = Tester(globs={}, verbose=0)
+ >>> t.rundict(d, "rundict_test") # _f is skipped
+ (0, 1)
+ >>> t = Tester(globs={}, verbose=0, isprivate=lambda x,y: 0)
+ >>> t.rundict(d, "rundict_test_pvt") # both are searched
+ (0, 2)
+ """
+
+ if not hasattr(d, "items"):
+ raise TypeError("Tester.rundict: d must support .items(); " +
+ `d`)
+ f = t = 0
+ for thisname, value in d.items():
+ if type(value) in (_FunctionType, _ClassType):
+ f2, t2 = self.__runone(value, name + "." + thisname)
+ f = f + f2
+ t = t + t2
+ return f, t
+
+ def run__test__(self, d, name):
+ """d, name -> Treat dict d like module.__test__.
+
+ Return (#failures, #tries).
+ See testmod.__doc__ for details.
+ """
+
+ failures = tries = 0
+ prefix = name + "."
+ savepvt = self.isprivate
+ try:
+ self.isprivate = lambda *args: 0
+ for k, v in d.items():
+ thisname = prefix + k
+ if type(v) is _StringType:
+ f, t = self.runstring(v, thisname)
+ elif type(v) in (_FunctionType, _ClassType):
+ f, t = self.rundoc(v, thisname)
+ else:
+ raise TypeError("Tester.run__test__: values in "
+ "dict must be strings, functions "
+ "or classes; " + `v`)
+ failures = failures + f
+ tries = tries + t
+ finally:
+ self.isprivate = savepvt
+ return failures, tries
+
+ def summarize(self, verbose=None):
+ """
+ verbose=None -> summarize results, return (#failures, #tests).
+
+ Print summary of test results to stdout.
+ Optional arg 'verbose' controls how wordy this is. By
+ default, use the verbose setting established by the
+ constructor.
+ """
+
+ if verbose is None:
+ verbose = self.verbose
+ notests = []
+ passed = []
+ failed = []
+ totalt = totalf = 0
+ for x in self.name2ft.items():
+ name, (f, t) = x
+ assert f <= t
+ totalt = totalt + t
+ totalf = totalf + f
+ if t == 0:
+ notests.append(name)
+ elif f == 0:
+ passed.append( (name, t) )
+ else:
+ failed.append(x)
+ if verbose:
+ if notests:
+ print len(notests), "items had no tests:"
+ notests.sort()
+ for thing in notests:
+ print " ", thing
+ if passed:
+ print len(passed), "items passed all tests:"
+ passed.sort()
+ for thing, count in passed:
+ print " %3d tests in %s" % (count, thing)
+ if failed:
+ print len(failed), "items had failures:"
+ failed.sort()
+ for thing, (f, t) in failed:
+ print " %3d of %3d in %s" % (f, t, thing)
+ if verbose:
+ print totalt, "tests in", len(self.name2ft), "items."
+ print totalt - totalf, "passed and", totalf, "failed."
+ if totalf:
+ print "***Test Failed***", totalf, "failures."
+ elif verbose:
+ print "Test passed."
+ return totalf, totalt
+
+ def merge(self, other):
+ """
+ other -> merge in test results from the other Tester instance.
+
+ If self and other both have a test result for something
+ with the same name, the (#failures, #tests) results are
+ summed, and a warning is printed to stdout.
+
+ >>> from doctest import Tester
+ >>> t1 = Tester(globs={}, verbose=0)
+ >>> t1.runstring('''
+ ... >>> x = 12
+ ... >>> print x
+ ... 12
+ ... ''', "t1example")
+ (0, 2)
+ >>>
+ >>> t2 = Tester(globs={}, verbose=0)
+ >>> t2.runstring('''
+ ... >>> x = 13
+ ... >>> print x
+ ... 13
+ ... ''', "t2example")
+ (0, 2)
+ >>> common = ">>> assert 1 + 2 == 3\\n"
+ >>> t1.runstring(common, "common")
+ (0, 1)
+ >>> t2.runstring(common, "common")
+ (0, 1)
+ >>> t1.merge(t2)
+ *** Tester.merge: 'common' in both testers; summing outcomes.
+ >>> t1.summarize(1)
+ 3 items passed all tests:
+ 2 tests in common
+ 2 tests in t1example
+ 2 tests in t2example
+ 6 tests in 3 items.
+ 6 passed and 0 failed.
+ Test passed.
+ (0, 6)
+ >>>
+ """
+
+ d = self.name2ft
+ for name, (f, t) in other.name2ft.items():
+ if d.has_key(name):
+ print "*** Tester.merge: '" + name + "' in both" \
+ " testers; summing outcomes."
+ f2, t2 = d[name]
+ f = f + f2
+ t = t + t2
+ d[name] = f, t
+
+ def __record_outcome(self, name, f, t):
+ if self.name2ft.has_key(name):
+ print "*** Warning: '" + name + "' was tested before;", \
+ "summing outcomes."
+ f2, t2 = self.name2ft[name]
+ f = f + f2
+ t = t + t2
+ self.name2ft[name] = f, t
+
+ def __runone(self, target, name):
+ if "." in name:
+ i = _string_rindex(name, ".")
+ prefix, base = name[:i], name[i+1:]
+ else:
+ prefix, base = "", base
+ if self.isprivate(prefix, base):
+ return 0, 0
+ return self.rundoc(target, name)
+
+master = None
+
+def testmod(m, name=None, globs=None, verbose=None, isprivate=None,
+ report=1):
+ """m, name=None, globs=None, verbose=None, isprivate=None, report=1
+
+ Test examples in docstrings in functions and classes reachable from
+ module m, starting with m.__doc__. Private names are skipped.
+
+ Also test examples reachable from dict m.__test__ if it exists and is
+ not None. m.__dict__ maps names to functions, classes and strings;
+ function and class docstrings are tested even if the name is private;
+ strings are tested directly, as if they were docstrings.
+
+ Return (#failures, #tests).
+
+ See doctest.__doc__ for an overview.
+
+ Optional keyword arg "name" gives the name of the module; by default
+ use m.__name__.
+
+ Optional keyword arg "globs" gives a dict to be used as the globals
+ when executing examples; by default, use m.__dict__. A copy of this
+ dict is actually used for each docstring, so that each docstring's
+ examples start with a clean slate.
+
+ Optional keyword arg "verbose" prints lots of stuff if true, prints
+ only failures if false; by default, it's true iff "-v" is in sys.argv.
+
+ Optional keyword arg "isprivate" specifies a function used to
+ determine whether a name is private. The default function is
+ doctest.is_private; see its docs for details.
+
+ Optional keyword arg "report" prints a summary at the end when true,
+ else prints nothing at the end. In verbose mode, the summary is
+ detailed, else very brief (in fact, empty if all tests passed).
+
+ Advanced tomfoolery: testmod runs methods of a local instance of
+ class doctest.Tester, then merges the results into (or creates)
+ global Tester instance doctest.master. Methods of doctest.master
+ can be called directly too, if you want to do something unusual.
+ Passing report=0 to testmod is especially useful then, to delay
+ displaying a summary. Invoke doctest.master.summarize(verbose)
+ when you're done fiddling.
+ """
+
+ global master
+
+ if type(m) is not _ModuleType:
+ raise TypeError("testmod: module required; " + `m`)
+ if name is None:
+ name = m.__name__
+ tester = Tester(m, globs=globs, verbose=verbose, isprivate=isprivate)
+ failures, tries = tester.rundoc(m, name)
+ f, t = tester.rundict(m.__dict__, name)
+ failures = failures + f
+ tries = tries + t
+ if hasattr(m, "__test__"):
+ testdict = m.__test__
+ if testdict:
+ if not hasattr(testdict, "items"):
+ raise TypeError("testmod: module.__test__ must support "
+ ".items(); " + `testdict`)
+ f, t = tester.run__test__(testdict, name + ".__test__")
+ failures = failures + f
+ tries = tries + t
+ if report:
+ tester.summarize()
+ if master is None:
+ master = tester
+ else:
+ master.merge(tester)
+ return failures, tries
+
+class _TestClass:
+ """
+ A pointless class, for sanity-checking of docstring testing.
+
+ Methods:
+ square()
+ get()
+
+ >>> _TestClass(13).get() + _TestClass(-12).get()
+ 1
+ >>> hex(_TestClass(13).square().get())
+ '0xa9'
+ """
+
+ def __init__(self, val):
+ """val -> _TestClass object with associated value val.
+
+ >>> t = _TestClass(123)
+ >>> print t.get()
+ 123
+ """
+
+ self.val = val
+
+ def square(self):
+ """square() -> square TestClass's associated value
+
+ >>> _TestClass(13).square().get()
+ 169
+ """
+
+ self.val = self.val ** 2
+ return self
+
+ def get(self):
+ """get() -> return TestClass's associated value.
+
+ >>> x = _TestClass(-42)
+ >>> print x.get()
+ -42
+ """
+
+ return self.val
+
+__test__ = {"_TestClass": _TestClass,
+ "string": r"""
+ Example of a string object, searched as-is.
+ >>> x = 1; y = 2
+ >>> x + y, x * y
+ (3, 2)
+ """
+ }
+
+def _test():
+ import doctest
+ return doctest.testmod(doctest)
+
+if __name__ == "__main__":
+ _test()
diff --git a/Imaging/encode.c b/Imaging/encode.c
new file mode 100644
index 0000000..0a57e74
--- /dev/null
+++ b/Imaging/encode.c
@@ -0,0 +1,531 @@
+/*
+ * The Python Imaging Library.
+ * $Id: encode.c 2751 2006-06-18 19:50:45Z fredrik $
+ *
+ * standard encoder interfaces for the Imaging library
+ *
+ * History:
+ * 1996-04-19 fl Based on decoders.c
+ * 1996-05-12 fl Compile cleanly as C++
+ * 1996-12-30 fl Plugged potential memory leak for tiled images
+ * 1997-01-03 fl Added GIF encoder
+ * 1997-01-05 fl Plugged encoder buffer leaks
+ * 1997-01-11 fl Added encode_to_file method
+ * 1998-03-09 fl Added mode/rawmode argument to encoders
+ * 1998-07-09 fl Added interlace argument to GIF encoder
+ * 1999-02-07 fl Added PCX encoder
+ *
+ * Copyright (c) 1997-2001 by Secret Labs AB
+ * Copyright (c) 1996-1997 by Fredrik Lundh
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+/* FIXME: make these pluggable! */
+
+#include "Python.h"
+
+#if PY_VERSION_HEX < 0x01060000
+#define PyObject_New PyObject_NEW
+#define PyObject_Del PyMem_DEL
+#endif
+
+#include "Imaging.h"
+#include "Gif.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> /* write */
+#endif
+
+/* -------------------------------------------------------------------- */
+/* Common */
+/* -------------------------------------------------------------------- */
+
+typedef struct {
+ PyObject_HEAD
+ int (*encode)(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+ struct ImagingCodecStateInstance state;
+ Imaging im;
+ PyObject* lock;
+} ImagingEncoderObject;
+
+staticforward PyTypeObject ImagingEncoderType;
+
+static ImagingEncoderObject*
+PyImaging_EncoderNew(int contextsize)
+{
+ ImagingEncoderObject *encoder;
+ void *context;
+
+ ImagingEncoderType.ob_type = &PyType_Type;
+
+ encoder = PyObject_New(ImagingEncoderObject, &ImagingEncoderType);
+ if (encoder == NULL)
+ return NULL;
+
+ /* Clear the encoder state */
+ memset(&encoder->state, 0, sizeof(encoder->state));
+
+ /* Allocate encoder context */
+ if (contextsize > 0) {
+ context = (void*) calloc(1, contextsize);
+ if (!context) {
+ Py_DECREF(encoder);
+ PyErr_NoMemory();
+ return NULL;
+ }
+ } else
+ context = 0;
+
+ /* Initialize encoder context */
+ encoder->state.context = context;
+
+ /* Target image */
+ encoder->lock = NULL;
+ encoder->im = NULL;
+
+ return encoder;
+}
+
+static void
+_dealloc(ImagingEncoderObject* encoder)
+{
+ free(encoder->state.buffer);
+ free(encoder->state.context);
+ Py_XDECREF(encoder->lock);
+ PyObject_Del(encoder);
+}
+
+static PyObject*
+_encode(ImagingEncoderObject* encoder, PyObject* args)
+{
+ PyObject* buf;
+ PyObject* result;
+ int status;
+
+ /* Encode to a Python string (allocated by this method) */
+
+ int bufsize = 16384;
+
+ if (!PyArg_ParseTuple(args, "|i", &bufsize))
+ return NULL;
+
+ buf = PyString_FromStringAndSize(NULL, bufsize);
+ if (!buf)
+ return NULL;
+
+ status = encoder->encode(encoder->im, &encoder->state,
+ (UINT8*) PyString_AsString(buf), bufsize);
+
+ /* adjust string length to avoid slicing in encoder */
+ if (_PyString_Resize(&buf, (status > 0) ? status : 0) < 0)
+ return NULL;
+
+ result = Py_BuildValue("iiO", status, encoder->state.errcode, buf);
+
+ Py_DECREF(buf); /* must release buffer!!! */
+
+ return result;
+}
+
+static PyObject*
+_encode_to_file(ImagingEncoderObject* encoder, PyObject* args)
+{
+ UINT8* buf;
+ int status;
+ ImagingSectionCookie cookie;
+
+ /* Encode to a file handle */
+
+ int fh;
+ int bufsize = 16384;
+
+ if (!PyArg_ParseTuple(args, "i|i", &fh, &bufsize))
+ return NULL;
+
+ /* Allocate an encoder buffer */
+ buf = (UINT8*) malloc(bufsize);
+ if (!buf) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ ImagingSectionEnter(&cookie);
+
+ do {
+
+ /* This replaces the inner loop in the ImageFile _save
+ function. */
+
+ status = encoder->encode(encoder->im, &encoder->state, buf, bufsize);
+
+ if (status > 0)
+ if (write(fh, buf, status) < 0) {
+ ImagingSectionLeave(&cookie);
+ free(buf);
+ return PyErr_SetFromErrno(PyExc_IOError);
+ }
+
+ } while (encoder->state.errcode == 0);
+
+ ImagingSectionLeave(&cookie);
+
+ free(buf);
+
+ return Py_BuildValue("i", encoder->state.errcode);
+}
+
+extern Imaging PyImaging_AsImaging(PyObject *op);
+
+static PyObject*
+_setimage(ImagingEncoderObject* encoder, PyObject* args)
+{
+ PyObject* op;
+ Imaging im;
+ ImagingCodecState state;
+ int x0, y0, x1, y1;
+
+ /* Define where image data should be stored */
+
+ x0 = y0 = x1 = y1 = 0;
+
+ /* FIXME: should publish the ImagingType descriptor */
+ if (!PyArg_ParseTuple(args, "O|(iiii)", &op, &x0, &y0, &x1, &y1))
+ return NULL;
+ im = PyImaging_AsImaging(op);
+ if (!im)
+ return NULL;
+
+ encoder->im = im;
+
+ state = &encoder->state;
+
+ if (x0 == 0 && x1 == 0) {
+ state->xsize = im->xsize;
+ state->ysize = im->ysize;
+ } else {
+ state->xoff = x0;
+ state->yoff = y0;
+ state->xsize = x1 - x0;
+ state->ysize = y1 - y0;
+ }
+
+ if (state->xsize <= 0 ||
+ state->xsize + state->xoff > im->xsize ||
+ state->ysize <= 0 ||
+ state->ysize + state->yoff > im->ysize) {
+ PyErr_SetString(PyExc_SystemError, "tile cannot extend outside image");
+ return NULL;
+ }
+
+ /* Allocate memory buffer (if bits field is set) */
+ if (state->bits > 0) {
+ state->bytes = (state->bits * state->xsize+7)/8;
+ state->buffer = (UINT8*) malloc(state->bytes);
+ if (!state->buffer) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ }
+
+ /* Keep a reference to the image object, to make sure it doesn't
+ go away before we do */
+ Py_INCREF(op);
+ Py_XDECREF(encoder->lock);
+ encoder->lock = op;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static struct PyMethodDef methods[] = {
+ {"encode", (PyCFunction)_encode, 1},
+ {"encode_to_file", (PyCFunction)_encode_to_file, 1},
+ {"setimage", (PyCFunction)_setimage, 1},
+ {NULL, NULL} /* sentinel */
+};
+
+static PyObject*
+_getattr(ImagingEncoderObject* self, char* name)
+{
+ return Py_FindMethod(methods, (PyObject*) self, name);
+}
+
+statichere PyTypeObject ImagingEncoderType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "ImagingEncoder", /*tp_name*/
+ sizeof(ImagingEncoderObject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor)_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ (getattrfunc)_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_hash*/
+};
+
+/* -------------------------------------------------------------------- */
+
+int
+get_packer(ImagingEncoderObject* encoder, const char* mode,
+ const char* rawmode)
+{
+ int bits;
+ ImagingShuffler pack;
+
+ pack = ImagingFindPacker(mode, rawmode, &bits);
+ if (!pack) {
+ Py_DECREF(encoder);
+ PyErr_SetString(PyExc_SystemError, "unknown raw mode");
+ return -1;
+ }
+
+ encoder->state.shuffle = pack;
+ encoder->state.bits = bits;
+
+ return 0;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* EPS */
+/* -------------------------------------------------------------------- */
+
+PyObject*
+PyImaging_EpsEncoderNew(PyObject* self, PyObject* args)
+{
+ ImagingEncoderObject* encoder;
+
+ encoder = PyImaging_EncoderNew(0);
+ if (encoder == NULL)
+ return NULL;
+
+ encoder->encode = ImagingEpsEncode;
+
+ return (PyObject*) encoder;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* GIF */
+/* -------------------------------------------------------------------- */
+
+PyObject*
+PyImaging_GifEncoderNew(PyObject* self, PyObject* args)
+{
+ ImagingEncoderObject* encoder;
+
+ char *mode;
+ char *rawmode;
+ int bits = 8;
+ int interlace = 0;
+ if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &bits, &interlace))
+ return NULL;
+
+ encoder = PyImaging_EncoderNew(sizeof(GIFENCODERSTATE));
+ if (encoder == NULL)
+ return NULL;
+
+ if (get_packer(encoder, mode, rawmode) < 0)
+ return NULL;
+
+ encoder->encode = ImagingGifEncode;
+
+ ((GIFENCODERSTATE*)encoder->state.context)->bits = bits;
+ ((GIFENCODERSTATE*)encoder->state.context)->interlace = interlace;
+
+ return (PyObject*) encoder;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* PCX */
+/* -------------------------------------------------------------------- */
+
+PyObject*
+PyImaging_PcxEncoderNew(PyObject* self, PyObject* args)
+{
+ ImagingEncoderObject* encoder;
+
+ char *mode;
+ char *rawmode;
+ int bits = 8;
+ if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &bits))
+ return NULL;
+
+ encoder = PyImaging_EncoderNew(0);
+ if (encoder == NULL)
+ return NULL;
+
+ if (get_packer(encoder, mode, rawmode) < 0)
+ return NULL;
+
+ encoder->encode = ImagingPcxEncode;
+
+ return (PyObject*) encoder;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* RAW */
+/* -------------------------------------------------------------------- */
+
+PyObject*
+PyImaging_RawEncoderNew(PyObject* self, PyObject* args)
+{
+ ImagingEncoderObject* encoder;
+
+ char *mode;
+ char *rawmode;
+ int stride = 0;
+ int ystep = 1;
+
+ if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &stride, &ystep))
+ return NULL;
+
+ encoder = PyImaging_EncoderNew(0);
+ if (encoder == NULL)
+ return NULL;
+
+ if (get_packer(encoder, mode, rawmode) < 0)
+ return NULL;
+
+ encoder->encode = ImagingRawEncode;
+
+ encoder->state.ystep = ystep;
+ encoder->state.count = stride;
+
+ return (PyObject*) encoder;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* XBM */
+/* -------------------------------------------------------------------- */
+
+PyObject*
+PyImaging_XbmEncoderNew(PyObject* self, PyObject* args)
+{
+ ImagingEncoderObject* encoder;
+
+ encoder = PyImaging_EncoderNew(0);
+ if (encoder == NULL)
+ return NULL;
+
+ if (get_packer(encoder, "1", "1;R") < 0)
+ return NULL;
+
+ encoder->encode = ImagingXbmEncode;
+
+ return (PyObject*) encoder;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* ZIP */
+/* -------------------------------------------------------------------- */
+
+#ifdef HAVE_LIBZ
+
+#include "Zip.h"
+
+PyObject*
+PyImaging_ZipEncoderNew(PyObject* self, PyObject* args)
+{
+ ImagingEncoderObject* encoder;
+
+ char* mode;
+ char* rawmode;
+ int optimize = 0;
+ char* dictionary = NULL;
+ int dictionary_size = 0;
+ if (!PyArg_ParseTuple(args, "ss|is#", &mode, &rawmode, &optimize,
+ &dictionary, &dictionary_size))
+ return NULL;
+
+ encoder = PyImaging_EncoderNew(sizeof(ZIPSTATE));
+ if (encoder == NULL)
+ return NULL;
+
+ if (get_packer(encoder, mode, rawmode) < 0)
+ return NULL;
+
+ encoder->encode = ImagingZipEncode;
+
+ if (rawmode[0] == 'P')
+ /* disable filtering */
+ ((ZIPSTATE*)encoder->state.context)->mode = ZIP_PNG_PALETTE;
+
+ ((ZIPSTATE*)encoder->state.context)->optimize = optimize;
+ ((ZIPSTATE*)encoder->state.context)->dictionary = dictionary;
+ ((ZIPSTATE*)encoder->state.context)->dictionary_size = dictionary_size;
+
+ return (PyObject*) encoder;
+}
+#endif
+
+
+/* -------------------------------------------------------------------- */
+/* JPEG */
+/* -------------------------------------------------------------------- */
+
+#ifdef HAVE_LIBJPEG
+
+/* We better define this encoder last in this file, so the following
+ undef's won't mess things up for the Imaging library proper. */
+
+#undef HAVE_PROTOTYPES
+#undef HAVE_STDDEF_H
+#undef HAVE_STDLIB_H
+#undef UINT8
+#undef UINT16
+#undef UINT32
+#undef INT8
+#undef INT16
+#undef INT32
+
+#include "Jpeg.h"
+
+PyObject*
+PyImaging_JpegEncoderNew(PyObject* self, PyObject* args)
+{
+ ImagingEncoderObject* encoder;
+
+ char *mode;
+ char *rawmode;
+ int quality = 0;
+ int progressive = 0;
+ int smooth = 0;
+ int optimize = 0;
+ int streamtype = 0; /* 0=interchange, 1=tables only, 2=image only */
+ int xdpi = 0, ydpi = 0;
+ if (!PyArg_ParseTuple(args, "ss|iiiiiii", &mode, &rawmode, &quality,
+ &progressive, &smooth, &optimize, &streamtype,
+ &xdpi, &ydpi))
+ return NULL;
+
+ encoder = PyImaging_EncoderNew(sizeof(JPEGENCODERSTATE));
+ if (encoder == NULL)
+ return NULL;
+
+ if (get_packer(encoder, mode, rawmode) < 0)
+ return NULL;
+
+ encoder->encode = ImagingJpegEncode;
+
+ ((JPEGENCODERSTATE*)encoder->state.context)->quality = quality;
+ ((JPEGENCODERSTATE*)encoder->state.context)->progressive = progressive;
+ ((JPEGENCODERSTATE*)encoder->state.context)->smooth = smooth;
+ ((JPEGENCODERSTATE*)encoder->state.context)->optimize = optimize;
+ ((JPEGENCODERSTATE*)encoder->state.context)->streamtype = streamtype;
+ ((JPEGENCODERSTATE*)encoder->state.context)->xdpi = xdpi;
+ ((JPEGENCODERSTATE*)encoder->state.context)->ydpi = ydpi;
+
+ return (PyObject*) encoder;
+}
+
+#endif
diff --git a/Imaging/libImaging/Access.c b/Imaging/libImaging/Access.c
new file mode 100644
index 0000000..6b2fcbd
--- /dev/null
+++ b/Imaging/libImaging/Access.c
@@ -0,0 +1,63 @@
+/*
+ * The Python Imaging Library
+ * $Id: Access.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * imaging access objects
+ *
+ * an access object can convert image data on the fly
+ *
+ * history:
+ * 98-12-29 fl Created
+ *
+ * Copyright (c) Secret Labs AB 1998.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+static void
+access_destroy(ImagingAccess access)
+{
+ /* nop */
+}
+
+static int
+access_getline(ImagingAccess access, char* buffer, int y)
+{
+ memcpy(buffer, access->im->image[y], access->im->linesize);
+ return 1;
+}
+
+ImagingAccess
+ImagingAccessNew(Imaging im)
+{
+ /* Create a standard access object */
+
+ ImagingAccess access;
+
+ access = calloc(1, sizeof(struct ImagingAccessInstance));
+ if (!access)
+ return (ImagingAccess) ImagingError_MemoryError();
+
+ access->im = im;
+
+ access->getline = access_getline;
+ access->destroy = access_destroy;
+
+ return access;
+}
+
+void
+ImagingAccessDelete(ImagingAccess access)
+{
+ if (!access)
+ return;
+
+ if (access->destroy)
+ access->destroy(access);
+
+ free(access);
+}
diff --git a/Imaging/libImaging/Antialias.c b/Imaging/libImaging/Antialias.c
new file mode 100644
index 0000000..089056e
--- /dev/null
+++ b/Imaging/libImaging/Antialias.c
@@ -0,0 +1,307 @@
+/*
+ * The Python Imaging Library
+ * $Id: Antialias.c 2408 2005-05-15 09:31:27Z Fredrik $
+ *
+ * pilopen antialiasing support
+ *
+ * history:
+ * 2002-03-09 fl Created (for PIL 1.1.3)
+ * 2002-03-10 fl Added support for mode "F"
+ *
+ * Copyright (c) 1997-2002 by Secret Labs AB
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+#include "Imaging.h"
+
+#include <math.h>
+
+/* resampling filters (from antialias.py) */
+
+struct filter {
+ float (*filter)(float x);
+ float support;
+};
+
+static inline float sinc_filter(float x)
+{
+ if (x == 0.0)
+ return 1.0;
+ x = x * M_PI;
+ return sin(x) / x;
+}
+
+static inline float antialias_filter(float x)
+{
+ /* lanczos (truncated sinc) */
+ if (-3.0 <= x && x < 3.0)
+ return sinc_filter(x) * sinc_filter(x/3);
+ return 0.0;
+}
+
+static struct filter ANTIALIAS = { antialias_filter, 3.0 };
+
+static inline float nearest_filter(float x)
+{
+ if (-0.5 <= x && x < 0.5)
+ return 1.0;
+ return 0.0;
+}
+
+static struct filter NEAREST = { nearest_filter, 0.5 };
+
+static inline float bilinear_filter(float x)
+{
+ if (x < 0.0)
+ x = -x;
+ if (x < 1.0)
+ return 1.0-x;
+ return 0.0;
+}
+
+static struct filter BILINEAR = { bilinear_filter, 1.0 };
+
+static inline float bicubic_filter(float x)
+{
+ /* FIXME: double-check this algorithm */
+ /* FIXME: for best results, "a" should be -0.5 to -1.0, but we'll
+ set it to zero for now, to match the 1.1 magnifying filter */
+#define a 0.0
+ if (x < 0.0)
+ x = -x;
+ if (x < 1.0)
+ return (((a + 2.0) * x) - (a + 3.0)) * x*x + 1;
+ if (x < 2.0)
+ return (((a * x) - 5*a) * x + 8) * x - 4*a;
+ return 0.0;
+#undef a
+}
+
+static struct filter BICUBIC = { bicubic_filter, 2.0 };
+
+Imaging
+ImagingStretch(Imaging imOut, Imaging imIn, int filter)
+{
+ /* FIXME: this is a quick and straightforward translation from a
+ python prototype. might need some further C-ification... */
+
+ ImagingSectionCookie cookie;
+ struct filter *filterp;
+ float support, scale, filterscale;
+ float center, ww, ss, ymin, ymax, xmin, xmax;
+ int xx, yy, x, y, b;
+ float *k;
+
+ /* check modes */
+ if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0)
+ return (Imaging) ImagingError_ModeError();
+
+ /* check filter */
+ switch (filter) {
+ case IMAGING_TRANSFORM_NEAREST:
+ filterp = &NEAREST;
+ break;
+ case IMAGING_TRANSFORM_ANTIALIAS:
+ filterp = &ANTIALIAS;
+ break;
+ case IMAGING_TRANSFORM_BILINEAR:
+ filterp = &BILINEAR;
+ break;
+ case IMAGING_TRANSFORM_BICUBIC:
+ filterp = &BICUBIC;
+ break;
+ default:
+ return (Imaging) ImagingError_ValueError(
+ "unsupported resampling filter"
+ );
+ }
+
+ if (imIn->ysize == imOut->ysize) {
+ /* prepare for horizontal stretch */
+ filterscale = scale = (float) imIn->xsize / imOut->xsize;
+ } else if (imIn->xsize == imOut->xsize) {
+ /* prepare for vertical stretch */
+ filterscale = scale = (float) imIn->ysize / imOut->ysize;
+ } else
+ return (Imaging) ImagingError_Mismatch();
+
+ /* determine support size (length of resampling filter) */
+ support = filterp->support;
+
+ if (filterscale < 1.0) {
+ filterscale = 1.0;
+ support = 0.5;
+ }
+
+ support = support * filterscale;
+
+ /* coefficient buffer (with rounding safety margin) */
+ k = malloc(((int) support * 2 + 10) * sizeof(float));
+ if (!k)
+ return (Imaging) ImagingError_MemoryError();
+
+ ImagingSectionEnter(&cookie);
+ if (imIn->xsize == imOut->xsize) {
+ /* vertical stretch */
+ for (yy = 0; yy < imOut->ysize; yy++) {
+ center = (yy + 0.5) * scale;
+ ww = 0.0;
+ ss = 1.0 / filterscale;
+ /* calculate filter weights */
+ ymin = floor(center - support);
+ if (ymin < 0.0)
+ ymin = 0.0;
+ ymax = ceil(center + support);
+ if (ymax > imIn->ysize)
+ ymax = imIn->ysize;
+ for (y = (int) ymin; y < (int) ymax; y++) {
+ float w = filterp->filter((y - center + 0.5) * ss) * ss;
+ k[y - (int) ymin] = w;
+ ww = ww + w;
+ }
+ if (ww == 0.0)
+ ww = 1.0;
+ else
+ ww = 1.0 / ww;
+ if (imIn->image8) {
+ /* 8-bit grayscale */
+ for (xx = 0; xx < imOut->xsize; xx++) {
+ ss = 0.0;
+ for (y = (int) ymin; y < (int) ymax; y++)
+ ss = ss + imIn->image8[y][xx] * k[y - (int) ymin];
+ ss = ss * ww + 0.5;
+ if (ss < 0.5)
+ imOut->image8[yy][xx] = 0;
+ else if (ss >= 255.0)
+ imOut->image8[yy][xx] = 255;
+ else
+ imOut->image8[yy][xx] = (UINT8) ss;
+ }
+ } else
+ switch(imIn->type) {
+ case IMAGING_TYPE_UINT8:
+ /* n-bit grayscale */
+ for (xx = 0; xx < imOut->xsize*4; xx++) {
+ /* FIXME: skip over unused pixels */
+ ss = 0.0;
+ for (y = (int) ymin; y < (int) ymax; y++)
+ ss = ss + (UINT8) imIn->image[y][xx] * k[y-(int) ymin];
+ ss = ss * ww + 0.5;
+ if (ss < 0.5)
+ imOut->image[yy][xx] = (UINT8) 0;
+ else if (ss >= 255.0)
+ imOut->image[yy][xx] = (UINT8) 255;
+ else
+ imOut->image[yy][xx] = (UINT8) ss;
+ }
+ break;
+ case IMAGING_TYPE_INT32:
+ /* 32-bit integer */
+ for (xx = 0; xx < imOut->xsize; xx++) {
+ ss = 0.0;
+ for (y = (int) ymin; y < (int) ymax; y++)
+ ss = ss + IMAGING_PIXEL_I(imIn, xx, y) * k[y - (int) ymin];
+ IMAGING_PIXEL_I(imOut, xx, yy) = ss * ww;
+ }
+ break;
+ case IMAGING_TYPE_FLOAT32:
+ /* 32-bit float */
+ for (xx = 0; xx < imOut->xsize; xx++) {
+ ss = 0.0;
+ for (y = (int) ymin; y < (int) ymax; y++)
+ ss = ss + IMAGING_PIXEL_F(imIn, xx, y) * k[y - (int) ymin];
+ IMAGING_PIXEL_F(imOut, xx, yy) = ss * ww;
+ }
+ break;
+ default:
+ ImagingSectionLeave(&cookie);
+ return (Imaging) ImagingError_ModeError();
+ }
+ }
+ } else {
+ /* horizontal stretch */
+ for (xx = 0; xx < imOut->xsize; xx++) {
+ center = (xx + 0.5) * scale;
+ ww = 0.0;
+ ss = 1.0 / filterscale;
+ xmin = floor(center - support);
+ if (xmin < 0.0)
+ xmin = 0.0;
+ xmax = ceil(center + support);
+ if (xmax > imIn->xsize)
+ xmax = imIn->xsize;
+ for (x = (int) xmin; x < (int) xmax; x++) {
+ float w = filterp->filter((x - center + 0.5) * ss) * ss;
+ k[x - (int) xmin] = w;
+ ww = ww + w;
+ }
+ if (ww == 0.0)
+ ww = 1.0;
+ else
+ ww = 1.0 / ww;
+ if (imIn->image8) {
+ /* 8-bit grayscale */
+ for (yy = 0; yy < imOut->ysize; yy++) {
+ ss = 0.0;
+ for (x = (int) xmin; x < (int) xmax; x++)
+ ss = ss + imIn->image8[yy][x] * k[x - (int) xmin];
+ ss = ss * ww + 0.5;
+ if (ss < 0.5)
+ imOut->image8[yy][xx] = (UINT8) 0;
+ else if (ss >= 255.0)
+ imOut->image8[yy][xx] = (UINT8) 255;
+ else
+ imOut->image8[yy][xx] = (UINT8) ss;
+ }
+ } else
+ switch(imIn->type) {
+ case IMAGING_TYPE_UINT8:
+ /* n-bit grayscale */
+ for (yy = 0; yy < imOut->ysize; yy++) {
+ for (b = 0; b < imIn->bands; b++) {
+ if (imIn->bands == 2 && b)
+ b = 3; /* hack to deal with LA images */
+ ss = 0.0;
+ for (x = (int) xmin; x < (int) xmax; x++)
+ ss = ss + (UINT8) imIn->image[yy][x*4+b] * k[x - (int) xmin];
+ ss = ss * ww + 0.5;
+ if (ss < 0.5)
+ imOut->image[yy][xx*4+b] = (UINT8) 0;
+ else if (ss >= 255.0)
+ imOut->image[yy][xx*4+b] = (UINT8) 255;
+ else
+ imOut->image[yy][xx*4+b] = (UINT8) ss;
+ }
+ }
+ break;
+ case IMAGING_TYPE_INT32:
+ /* 32-bit integer */
+ for (yy = 0; yy < imOut->ysize; yy++) {
+ ss = 0.0;
+ for (x = (int) xmin; x < (int) xmax; x++)
+ ss = ss + IMAGING_PIXEL_I(imIn, x, yy) * k[x - (int) xmin];
+ IMAGING_PIXEL_I(imOut, xx, yy) = ss * ww;
+ }
+ break;
+ case IMAGING_TYPE_FLOAT32:
+ /* 32-bit float */
+ for (yy = 0; yy < imOut->ysize; yy++) {
+ ss = 0.0;
+ for (x = (int) xmin; x < (int) xmax; x++)
+ ss = ss + IMAGING_PIXEL_F(imIn, x, yy) * k[x - (int) xmin];
+ IMAGING_PIXEL_F(imOut, xx, yy) = ss * ww;
+ }
+ break;
+ default:
+ ImagingSectionLeave(&cookie);
+ return (Imaging) ImagingError_ModeError();
+ }
+ }
+ }
+ ImagingSectionLeave(&cookie);
+
+ free(k);
+
+ return imOut;
+}
diff --git a/Imaging/libImaging/Bands.c b/Imaging/libImaging/Bands.c
new file mode 100644
index 0000000..0952fb6
--- /dev/null
+++ b/Imaging/libImaging/Bands.c
@@ -0,0 +1,129 @@
+/*
+ * The Python Imaging Library
+ * $Id: Bands.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * stuff to extract and paste back individual bands
+ *
+ * history:
+ * 1996-03-20 fl Created
+ * 1997-08-27 fl Fixed putband for single band targets.
+ * 2003-09-26 fl Fixed getband/putband for 2-band images (LA, PA).
+ *
+ * Copyright (c) 1997-2003 by Secret Labs AB.
+ * Copyright (c) 1996-1997 by Fredrik Lundh.
+ *
+ * See the README file for details on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+#define CLIP(x) ((x) <= 0 ? 0 : (x) < 256 ? (x) : 255)
+
+
+Imaging
+ImagingGetBand(Imaging imIn, int band)
+{
+ Imaging imOut;
+ int x, y;
+
+ /* Check arguments */
+ if (!imIn || imIn->type != IMAGING_TYPE_UINT8)
+ return (Imaging) ImagingError_ModeError();
+
+ if (band < 0 || band >= imIn->bands)
+ return (Imaging) ImagingError_ValueError("band index out of range");
+
+ /* Shortcuts */
+ if (imIn->bands == 1)
+ return ImagingCopy(imIn);
+
+ /* Special case for LXXA etc */
+ if (imIn->bands == 2 && band == 1)
+ band = 3;
+
+ imOut = ImagingNew("L", imIn->xsize, imIn->ysize);
+ if (!imOut)
+ return NULL;
+
+ /* Extract band from image */
+ for (y = 0; y < imIn->ysize; y++) {
+ UINT8* in = (UINT8*) imIn->image[y] + band;
+ UINT8* out = imOut->image8[y];
+ for (x = 0; x < imIn->xsize; x++) {
+ out[x] = *in;
+ in += 4;
+ }
+ }
+
+ return imOut;
+}
+
+Imaging
+ImagingPutBand(Imaging imOut, Imaging imIn, int band)
+{
+ int x, y;
+
+ /* Check arguments */
+ if (!imIn || imIn->bands != 1 || !imOut)
+ return (Imaging) ImagingError_ModeError();
+
+ if (band < 0 || band >= imOut->bands)
+ return (Imaging) ImagingError_ValueError("band index out of range");
+
+ if (imIn->type != imOut->type ||
+ imIn->xsize != imOut->xsize ||
+ imIn->ysize != imOut->ysize)
+ return (Imaging) ImagingError_Mismatch();
+
+ /* Shortcuts */
+ if (imOut->bands == 1)
+ return ImagingCopy2(imOut, imIn);
+
+ /* Special case for LXXA etc */
+ if (imOut->bands == 2 && band == 1)
+ band = 3;
+
+ /* Insert band into image */
+ for (y = 0; y < imIn->ysize; y++) {
+ UINT8* in = imIn->image8[y];
+ UINT8* out = (UINT8*) imOut->image[y] + band;
+ for (x = 0; x < imIn->xsize; x++) {
+ *out = in[x];
+ out += 4;
+ }
+ }
+
+ return imOut;
+}
+
+Imaging
+ImagingFillBand(Imaging imOut, int band, int color)
+{
+ int x, y;
+
+ /* Check arguments */
+ if (!imOut || imOut->type != IMAGING_TYPE_UINT8)
+ return (Imaging) ImagingError_ModeError();
+
+ if (band < 0 || band >= imOut->bands)
+ return (Imaging) ImagingError_ValueError("band index out of range");
+
+ /* Special case for LXXA etc */
+ if (imOut->bands == 2 && band == 1)
+ band = 3;
+
+ color = CLIP(color);
+
+ /* Insert color into image */
+ for (y = 0; y < imOut->ysize; y++) {
+ UINT8* out = (UINT8*) imOut->image[y] + band;
+ for (x = 0; x < imOut->xsize; x++) {
+ *out = (UINT8) color;
+ out += 4;
+ }
+ }
+
+ return imOut;
+}
diff --git a/Imaging/libImaging/Bit.h b/Imaging/libImaging/Bit.h
new file mode 100644
index 0000000..56e3a17
--- /dev/null
+++ b/Imaging/libImaging/Bit.h
@@ -0,0 +1,30 @@
+/* Bit.h */
+
+typedef struct {
+
+ /* CONFIGURATION */
+
+ /* Number of bits per pixel */
+ int bits;
+
+ /* Line padding (0 or 8) */
+ int pad;
+
+ /* Fill order */
+ /* 0=msb/msb, 1=msbfill/lsbshift, 2=lsbfill/msbshift, 3=lsb/lsb */
+ int fill;
+
+ /* Signed integers (0=unsigned, 1=signed) */
+ int sign;
+
+ /* Lookup table (not implemented) */
+ unsigned long lutsize;
+ FLOAT32* lut;
+
+ /* INTERNAL */
+ unsigned long mask;
+ unsigned long signmask;
+ unsigned long bitbuffer;
+ int bitcount;
+
+} BITSTATE;
diff --git a/Imaging/libImaging/BitDecode.c b/Imaging/libImaging/BitDecode.c
new file mode 100644
index 0000000..fef719e
--- /dev/null
+++ b/Imaging/libImaging/BitDecode.c
@@ -0,0 +1,138 @@
+/*
+ * The Python Imaging Library.
+ * $Id: BitDecode.c 2278 2005-02-07 20:27:33Z fredrik $
+ *
+ * decoder for packed bitfields (converts to floating point)
+ *
+ * history:
+ * 97-05-31 fl created (much more than originally intended)
+ *
+ * Copyright (c) Fredrik Lundh 1997.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+#include "Bit.h"
+
+
+int
+ImagingBitDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ BITSTATE* bitstate = state->context;
+ UINT8* ptr;
+
+ if (state->state == 0) {
+
+ /* Initialize context variables */
+
+ /* this decoder only works for float32 image buffers */
+ if (im->type != IMAGING_TYPE_FLOAT32) {
+ state->errcode = IMAGING_CODEC_CONFIG;
+ return -1;
+ }
+
+ /* sanity check */
+ if (bitstate->bits < 1 || bitstate->bits >= 32) {
+ state->errcode = IMAGING_CODEC_CONFIG;
+ return -1;
+ }
+
+ bitstate->mask = (1<<bitstate->bits)-1;
+
+ if (bitstate->sign)
+ bitstate->signmask = (1<<(bitstate->bits-1));
+
+ /* check image orientation */
+ if (state->ystep < 0) {
+ state->y = state->ysize-1;
+ state->ystep = -1;
+ } else
+ state->ystep = 1;
+
+ state->state = 1;
+
+ }
+
+ ptr = buf;
+
+ while (bytes > 0) {
+
+ UINT8 byte = *ptr;
+
+ ptr++;
+ bytes--;
+
+ /* get a byte from the input stream and insert in the bit buffer */
+ if (bitstate->fill&1)
+ /* fill MSB first */
+ bitstate->bitbuffer |= (unsigned long) byte << bitstate->bitcount;
+ else
+ /* fill LSB first */
+ bitstate->bitbuffer = (bitstate->bitbuffer << 8) | byte;
+
+ bitstate->bitcount += 8;
+
+ while (bitstate->bitcount >= bitstate->bits) {
+
+ /* get a pixel from the bit buffer */
+ unsigned long data;
+ FLOAT32 pixel;
+
+ if (bitstate->fill&2) {
+ /* store LSB first */
+ data = bitstate->bitbuffer & bitstate->mask;
+ if (bitstate->bitcount > 32)
+ /* bitbuffer overflow; restore it from last input byte */
+ bitstate->bitbuffer = byte >> (8 - (bitstate->bitcount -
+ bitstate->bits));
+ else
+ bitstate->bitbuffer >>= bitstate->bits;
+ } else
+ /* store MSB first */
+ data = (bitstate->bitbuffer >> (bitstate->bitcount -
+ bitstate->bits))
+ & bitstate->mask;
+
+ bitstate->bitcount -= bitstate->bits;
+
+ if (bitstate->lutsize > 0) {
+ /* map through lookup table */
+ if (data <= 0)
+ pixel = bitstate->lut[0];
+ else if (data >= bitstate->lutsize)
+ pixel = bitstate->lut[bitstate->lutsize-1];
+ else
+ pixel = bitstate->lut[data];
+ } else {
+ /* convert */
+ if (data & bitstate->signmask)
+ /* image memory contains signed data */
+ pixel = (FLOAT32) (INT32) (data | ~bitstate->mask);
+ else
+ pixel = (FLOAT32) data;
+ }
+
+ *(FLOAT32*)(&im->image32[state->y][state->x]) = pixel;
+
+ /* step forward */
+ if (++state->x >= state->xsize) {
+ /* new line */
+ state->y += state->ystep;
+ if (state->y < 0 || state->y >= state->ysize) {
+ /* end of file (errcode = 0) */
+ return -1;
+ }
+ state->x = 0;
+ /* reset bit buffer */
+ if (bitstate->pad > 0)
+ bitstate->bitcount = 0;
+ }
+ }
+ }
+
+ return ptr - buf;
+}
diff --git a/Imaging/libImaging/Blend.c b/Imaging/libImaging/Blend.c
new file mode 100644
index 0000000..4d8db66
--- /dev/null
+++ b/Imaging/libImaging/Blend.c
@@ -0,0 +1,79 @@
+/*
+ * The Python Imaging Library
+ * $Id: Blend.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * interpolate between two existing images
+ *
+ * history:
+ * 96-03-20 fl Created
+ * 96-05-18 fl Simplified blend expression
+ * 96-10-05 fl Fixed expression bug, special case for interpolation
+ *
+ * Copyright (c) Fredrik Lundh 1996.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for details on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+Imaging
+ImagingBlend(Imaging imIn1, Imaging imIn2, float alpha)
+{
+ Imaging imOut;
+ int x, y;
+
+ /* Check arguments */
+ if (!imIn1 || !imIn2 || imIn1->type != IMAGING_TYPE_UINT8)
+ return ImagingError_ModeError();
+ if (imIn1->type != imIn2->type ||
+ imIn1->bands != imIn2->bands ||
+ imIn1->xsize != imIn2->xsize ||
+ imIn1->ysize != imIn2->ysize)
+ return ImagingError_Mismatch();
+
+ /* Shortcuts */
+ if (alpha == 0.0)
+ return ImagingCopy(imIn1);
+ else if (alpha == 1.0)
+ return ImagingCopy(imIn2);
+
+ imOut = ImagingNew(imIn1->mode, imIn1->xsize, imIn1->ysize);
+ if (!imOut)
+ return NULL;
+
+ ImagingCopyInfo(imOut, imIn1);
+
+ if (alpha >= 0 && alpha <= 1.0) {
+ /* Interpolate between bands */
+ for (y = 0; y < imIn1->ysize; y++) {
+ UINT8* in1 = (UINT8*) imIn1->image[y];
+ UINT8* in2 = (UINT8*) imIn2->image[y];
+ UINT8* out = (UINT8*) imOut->image[y];
+ for (x = 0; x < imIn1->linesize; x++)
+ out[x] = (UINT8)
+ ((int) in1[x] + alpha * ((int) in2[x] - (int) in1[x]));
+ }
+ } else {
+ /* Extrapolation; must make sure to clip resulting values */
+ for (y = 0; y < imIn1->ysize; y++) {
+ UINT8* in1 = (UINT8*) imIn1->image[y];
+ UINT8* in2 = (UINT8*) imIn2->image[y];
+ UINT8* out = (UINT8*) imOut->image[y];
+ for (x = 0; x < imIn1->linesize; x++) {
+ float temp =
+ ((int) in1[x] + alpha * ((int) in2[x] - (int) in1[x]));
+ if (temp <= 0.0)
+ out[x] = 0;
+ else if (temp >= 255.0)
+ out[x] = 255;
+ else
+ out[x] = (UINT8) temp;
+ }
+ }
+ }
+
+ return imOut;
+}
diff --git a/Imaging/libImaging/Chops.c b/Imaging/libImaging/Chops.c
new file mode 100644
index 0000000..fdd13fd
--- /dev/null
+++ b/Imaging/libImaging/Chops.c
@@ -0,0 +1,148 @@
+/*
+ * The Python Imaging Library
+ * $Id: Chops.c 2506 2005-09-10 14:52:13Z Fredrik $
+ *
+ * basic channel operations
+ *
+ * history:
+ * 1996-03-28 fl Created
+ * 1996-08-13 fl Added and/or/xor for "1" images
+ * 1996-12-14 fl Added add_modulo, sub_modulo
+ * 2005-09-10 fl Fixed output values from and/or/xor
+ *
+ * Copyright (c) 1996 by Fredrik Lundh.
+ * Copyright (c) 1997 by Secret Labs AB.
+ *
+ * See the README file for details on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+#define CHOP(operation, mode)\
+ int x, y;\
+ Imaging imOut;\
+ imOut = create(imIn1, imIn2, mode);\
+ if (!imOut)\
+ return NULL;\
+ for (y = 0; y < imOut->ysize; y++) {\
+ UINT8* out = (UINT8*) imOut->image[y];\
+ UINT8* in1 = (UINT8*) imIn1->image[y];\
+ UINT8* in2 = (UINT8*) imIn2->image[y];\
+ for (x = 0; x < imOut->linesize; x++) {\
+ int temp = operation;\
+ if (temp <= 0)\
+ out[x] = 0;\
+ else if (temp >= 255)\
+ out[x] = 255;\
+ else\
+ out[x] = temp;\
+ }\
+ }\
+ return imOut;
+
+#define CHOP2(operation, mode)\
+ int x, y;\
+ Imaging imOut;\
+ imOut = create(imIn1, imIn2, mode);\
+ if (!imOut)\
+ return NULL;\
+ for (y = 0; y < imOut->ysize; y++) {\
+ UINT8* out = (UINT8*) imOut->image[y];\
+ UINT8* in1 = (UINT8*) imIn1->image[y];\
+ UINT8* in2 = (UINT8*) imIn2->image[y];\
+ for (x = 0; x < imOut->linesize; x++) {\
+ out[x] = operation;\
+ }\
+ }\
+ return imOut;
+
+static Imaging
+create(Imaging im1, Imaging im2, char* mode)
+{
+ int xsize, ysize;
+
+ if (!im1 || !im2 || im1->type != IMAGING_TYPE_UINT8 ||
+ (mode != NULL && (strcmp(im1->mode, "1") || strcmp(im2->mode, "1"))))
+ return (Imaging) ImagingError_ModeError();
+ if (im1->type != im2->type ||
+ im1->bands != im2->bands)
+ return (Imaging) ImagingError_Mismatch();
+
+ xsize = (im1->xsize < im2->xsize) ? im1->xsize : im2->xsize;
+ ysize = (im1->ysize < im2->ysize) ? im1->ysize : im2->ysize;
+
+ return ImagingNew(im1->mode, xsize, ysize);
+}
+
+Imaging
+ImagingChopLighter(Imaging imIn1, Imaging imIn2)
+{
+ CHOP((in1[x] > in2[x]) ? in1[x] : in2[x], NULL);
+}
+
+Imaging
+ImagingChopDarker(Imaging imIn1, Imaging imIn2)
+{
+ CHOP((in1[x] < in2[x]) ? in1[x] : in2[x], NULL);
+}
+
+Imaging
+ImagingChopDifference(Imaging imIn1, Imaging imIn2)
+{
+ CHOP(abs((int) in1[x] - (int) in2[x]), NULL);
+}
+
+Imaging
+ImagingChopMultiply(Imaging imIn1, Imaging imIn2)
+{
+ CHOP((int) in1[x] * (int) in2[x] / 255, NULL);
+}
+
+Imaging
+ImagingChopScreen(Imaging imIn1, Imaging imIn2)
+{
+ CHOP(255 - ((int) (255 - in1[x]) * (int) (255 - in2[x])) / 255, NULL);
+}
+
+Imaging
+ImagingChopAdd(Imaging imIn1, Imaging imIn2, float scale, int offset)
+{
+ CHOP(((int) in1[x] + (int) in2[x]) / scale + offset, NULL);
+}
+
+Imaging
+ImagingChopSubtract(Imaging imIn1, Imaging imIn2, float scale, int offset)
+{
+ CHOP(((int) in1[x] - (int) in2[x]) / scale + offset, NULL);
+}
+
+Imaging
+ImagingChopAnd(Imaging imIn1, Imaging imIn2)
+{
+ CHOP2((in1[x] && in2[x]) ? 255 : 0, "1");
+}
+
+Imaging
+ImagingChopOr(Imaging imIn1, Imaging imIn2)
+{
+ CHOP2((in1[x] || in2[x]) ? 255 : 0, "1");
+}
+
+Imaging
+ImagingChopXor(Imaging imIn1, Imaging imIn2)
+{
+ CHOP2(((in1[x] != 0) ^ (in2[x] != 0)) ? 255 : 0, "1");
+}
+
+Imaging
+ImagingChopAddModulo(Imaging imIn1, Imaging imIn2)
+{
+ CHOP2(in1[x] + in2[x], NULL);
+}
+
+Imaging
+ImagingChopSubtractModulo(Imaging imIn1, Imaging imIn2)
+{
+ CHOP2(in1[x] - in2[x], NULL);
+}
diff --git a/Imaging/libImaging/Convert.c b/Imaging/libImaging/Convert.c
new file mode 100644
index 0000000..26bd01c
--- /dev/null
+++ b/Imaging/libImaging/Convert.c
@@ -0,0 +1,1080 @@
+/*
+ * The Python Imaging Library
+ * $Id: Convert.c 2591 2005-12-08 21:25:29Z fredrik $
+ *
+ * convert images
+ *
+ * history:
+ * 1995-06-15 fl created
+ * 1995-11-28 fl added some "RGBA" and "CMYK" conversions
+ * 1996-04-22 fl added "1" conversions (same as "L")
+ * 1996-05-05 fl added palette conversions (hack)
+ * 1996-07-23 fl fixed "1" conversions to zero/non-zero convention
+ * 1996-11-01 fl fixed "P" to "L" and "RGB" to "1" conversions
+ * 1996-12-29 fl set alpha byte in RGB converters
+ * 1997-05-12 fl added ImagingConvert2
+ * 1997-05-30 fl added floating point support
+ * 1997-08-27 fl added "P" to "1" and "P" to "F" conversions
+ * 1998-01-11 fl added integer support
+ * 1998-07-01 fl added "YCbCr" support
+ * 1998-07-02 fl added "RGBX" conversions (sort of)
+ * 1998-07-04 fl added floyd-steinberg dithering
+ * 1998-07-12 fl changed "YCrCb" to "YCbCr" (!)
+ * 1998-12-29 fl added basic "I;16" and "I;16B" conversions
+ * 1999-02-03 fl added "RGBa", and "BGR" conversions (experimental)
+ * 2003-09-26 fl added "LA" and "PA" conversions (experimental)
+ * 2005-05-05 fl fixed "P" to "1" threshold
+ * 2005-12-08 fl fixed palette memory leak in topalette
+ *
+ * Copyright (c) 1997-2005 by Secret Labs AB.
+ * Copyright (c) 1995-1997 by Fredrik Lundh.
+ *
+ * See the README file for details on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+#define CLIP(v) ((v) <= 0 ? 0 : (v) >= 255 ? 255 : (v))
+#define CLIP16(v) ((v) <= -32768 ? -32768 : (v) >= 32767 ? 32767 : (v))
+
+/* like (a * b + 127) / 255), but much faster on most platforms */
+#define MULDIV255(a, b, tmp)\
+ (tmp = (a) * (b) + 128, ((((tmp) >> 8) + (tmp)) >> 8))
+
+/* ITU-R Recommendation 601-2 (assuming nonlinear RGB) */
+#define L(rgb)\
+ ((INT32) (rgb)[0]*299 + (INT32) (rgb)[1]*587 + (INT32) (rgb)[2]*114)
+
+/* ------------------- */
+/* 1 (bit) conversions */
+/* ------------------- */
+
+static void
+bit2l(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++)
+ *out++ = (*in++ != 0) ? 255 : 0;
+}
+
+static void
+bit2rgb(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++) {
+ UINT8 v = (*in++ != 0) ? 255 : 0;
+ *out++ = v;
+ *out++ = v;
+ *out++ = v;
+ *out++ = 255;
+ }
+}
+
+static void
+bit2cmyk(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++) {
+ *out++ = 0;
+ *out++ = 0;
+ *out++ = 0;
+ *out++ = (*in++ != 0) ? 0 : 255;
+ }
+}
+
+static void
+bit2ycbcr(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++) {
+ *out++ = (*in++ != 0) ? 255 : 0;
+ *out++ = 128;
+ *out++ = 128;
+ *out++ = 255;
+ }
+}
+
+/* ----------------- */
+/* RGB/L conversions */
+/* ----------------- */
+
+static void
+l2bit(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++)
+ *out++ = (*in++ >= 128) ? 255 : 0;
+}
+
+static void
+l2la(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++) {
+ UINT8 v = *in++;
+ *out++ = v;
+ *out++ = v;
+ *out++ = v;
+ *out++ = 255;
+ }
+}
+
+static void
+l2rgb(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++) {
+ UINT8 v = *in++;
+ *out++ = v;
+ *out++ = v;
+ *out++ = v;
+ *out++ = 255;
+ }
+}
+
+static void
+la2l(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++, in += 4)
+ *out++ = in[0];
+}
+
+static void
+la2rgb(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++, in += 4) {
+ UINT8 v = in[0];
+ *out++ = v;
+ *out++ = v;
+ *out++ = v;
+ *out++ = in[3];
+ }
+}
+
+static void
+rgb2bit(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++, in += 4)
+ /* ITU-R Recommendation 601-2 (assuming nonlinear RGB) */
+ *out++ = (L(in) >= 128000) ? 255 : 0;
+}
+
+static void
+rgb2l(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++, in += 4)
+ /* ITU-R Recommendation 601-2 (assuming nonlinear RGB) */
+ *out++ = L(in) / 1000;
+}
+
+static void
+rgb2la(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++, in += 4, out += 4) {
+ /* ITU-R Recommendation 601-2 (assuming nonlinear RGB) */
+ out[0] = out[1] = out[2] = L(in) / 1000;
+ out[3] = 255;
+ }
+}
+
+static void
+rgb2i(UINT8* out_, const UINT8* in, int xsize)
+{
+ int x;
+ INT32* out = (INT32*) out_;
+ for (x = 0; x < xsize; x++, in += 4)
+ *out++ = L(in) / 1000;
+}
+
+static void
+rgb2f(UINT8* out_, const UINT8* in, int xsize)
+{
+ int x;
+ FLOAT32* out = (FLOAT32*) out_;
+ for (x = 0; x < xsize; x++, in += 4)
+ *out++ = L(in) / 1000.0F;
+}
+
+static void
+rgb2bgr15(UINT8* out_, const UINT8* in, int xsize)
+{
+ int x;
+ UINT16* out = (UINT16*) out_;
+ for (x = 0; x < xsize; x++, in += 4)
+ *out++ =
+ ((((UINT16)in[0])<<8)&0x7c00) +
+ ((((UINT16)in[1])<<2)&0x03e0) +
+ ((((UINT16)in[2])>>3)&0x001f);
+}
+
+static void
+rgb2bgr16(UINT8* out_, const UINT8* in, int xsize)
+{
+ int x;
+ UINT16* out = (UINT16*) out_;
+ for (x = 0; x < xsize; x++, in += 4)
+ *out++ =
+ ((((UINT16)in[0])<<8)&0xf800) +
+ ((((UINT16)in[1])<<3)&0x07e0) +
+ ((((UINT16)in[2])>>3)&0x001f);
+}
+
+static void
+rgb2bgr24(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++, in += 4) {
+ *out++ = in[2];
+ *out++ = in[1];
+ *out++ = in[0];
+ }
+}
+
+/* ---------------- */
+/* RGBA conversions */
+/* ---------------- */
+
+static void
+rgb2rgba(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++) {
+ *out++ = *in++;
+ *out++ = *in++;
+ *out++ = *in++;
+ *out++ = 255; in++;
+ }
+}
+
+static void
+rgba2la(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++, in += 4, out += 4) {
+ /* ITU-R Recommendation 601-2 (assuming nonlinear RGB) */
+ out[0] = out[1] = out[2] = L(in) / 1000;
+ out[3] = in[3];
+ }
+}
+
+static void
+rgba2rgb(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++) {
+ *out++ = *in++;
+ *out++ = *in++;
+ *out++ = *in++;
+ *out++ = 255; in++;
+ }
+}
+
+static void
+rgba2rgba(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ unsigned int alpha, tmp;
+ for (x = 0; x < xsize; x++) {
+ alpha = in[3];
+ *out++ = MULDIV255(*in++, alpha, tmp);
+ *out++ = MULDIV255(*in++, alpha, tmp);
+ *out++ = MULDIV255(*in++, alpha, tmp);
+ *out++ = *in++;
+ }
+}
+
+/* ---------------- */
+/* CMYK conversions */
+/* ---------------- */
+
+static void
+l2cmyk(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++) {
+ *out++ = 0;
+ *out++ = 0;
+ *out++ = 0;
+ *out++ = ~(*in++);
+ }
+}
+
+static void
+rgb2cmyk(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++) {
+ /* Note: no undercolour removal */
+ *out++ = ~(*in++);
+ *out++ = ~(*in++);
+ *out++ = ~(*in++);
+ *out++ = 0; in++;
+ }
+}
+
+static void
+cmyk2rgb(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++, in += 4) {
+ *out++ = CLIP(255 - (in[0] + in[3]));
+ *out++ = CLIP(255 - (in[1] + in[3]));
+ *out++ = CLIP(255 - (in[2] + in[3]));
+ *out++ = 255;
+ }
+}
+
+/* ------------- */
+/* I conversions */
+/* ------------- */
+
+static void
+bit2i(UINT8* out_, const UINT8* in, int xsize)
+{
+ int x;
+ INT32* out = (INT32*) out_;
+ for (x = 0; x < xsize; x++)
+ *out++ = (*in++ != 0) ? 255 : 0;
+}
+
+static void
+l2i(UINT8* out_, const UINT8* in, int xsize)
+{
+ int x;
+ INT32* out = (INT32*) out_;
+ for (x = 0; x < xsize; x++)
+ *out++ = (INT32) *in++;
+}
+
+static void
+i2l(UINT8* out, const UINT8* in_, int xsize)
+{
+ int x;
+ INT32* in = (INT32*) in_;
+ for (x = 0; x < xsize; x++, in++, out++) {
+ if (*in <= 0)
+ *out = 0;
+ else if (*in >= 255)
+ *out = 255;
+ else
+ *out = (UINT8) *in;
+ }
+}
+
+static void
+i2f(UINT8* out_, const UINT8* in_, int xsize)
+{
+ int x;
+ INT32* in = (INT32*) in_;
+ FLOAT32* out = (FLOAT32*) out_;
+ for (x = 0; x < xsize; x++)
+ *out++ = (FLOAT32) *in++;
+}
+
+/* ------------- */
+/* F conversions */
+/* ------------- */
+
+static void
+bit2f(UINT8* out_, const UINT8* in, int xsize)
+{
+ int x;
+ FLOAT32* out = (FLOAT32*) out_;
+ for (x = 0; x < xsize; x++)
+ *out++ = (*in++ != 0) ? 255.0F : 0.0F;
+}
+
+static void
+l2f(UINT8* out_, const UINT8* in, int xsize)
+{
+ int x;
+ FLOAT32* out = (FLOAT32*) out_;
+ for (x = 0; x < xsize; x++)
+ *out++ = (FLOAT32) *in++;
+}
+
+static void
+f2l(UINT8* out, const UINT8* in_, int xsize)
+{
+ int x;
+ FLOAT32* in = (FLOAT32*) in_;
+ for (x = 0; x < xsize; x++, in++, out++) {
+ if (*in <= 0.0)
+ *out = 0;
+ else if (*in >= 255.0)
+ *out = 255;
+ else
+ *out = (UINT8) *in;
+ }
+}
+
+static void
+f2i(UINT8* out_, const UINT8* in_, int xsize)
+{
+ int x;
+ FLOAT32* in = (FLOAT32*) in_;
+ INT32* out = (INT32*) out_;
+ for (x = 0; x < xsize; x++)
+ *out++ = (INT32) *in++;
+}
+
+/* ----------------- */
+/* YCbCr conversions */
+/* ----------------- */
+
+/* See ConvertYCbCr.c for RGB/YCbCr tables */
+
+static void
+l2ycbcr(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++) {
+ *out++ = *in++;
+ *out++ = 128;
+ *out++ = 128;
+ *out++ = 255;
+ }
+}
+
+static void
+ycbcr2l(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++, in += 4)
+ *out++ = in[0];
+}
+
+/* ------------------------- */
+/* I;16 (16-bit) conversions */
+/* ------------------------- */
+
+static void
+i2i16(UINT8* out, const UINT8* in_, int xsize)
+{
+ int x, v;
+ INT32* in = (INT32*) in_;
+ for (x = 0; x < xsize; x++, in++) {
+ v = CLIP16(*in);
+ *out++ = (UINT8) v;
+ *out++ = (UINT8) (v >> 8);
+ }
+}
+
+static void
+l2i16(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++, in++) {
+ *out++ = *in;
+ *out++ = 0;
+ }
+}
+
+static void
+i2i16b(UINT8* out, const UINT8* in_, int xsize)
+{
+ int x, v;
+ INT32* in = (INT32*) in_;
+ for (x = 0; x < xsize; x++, in++) {
+ v = CLIP16(*in);
+ *out++ = (UINT8) (v >> 8);
+ *out++ = (UINT8) v;
+ }
+}
+
+static void
+i162i(UINT8* out_, const UINT8* in, int xsize)
+{
+ int x;
+ INT32* out = (INT32*) out_;
+ for (x = 0; x < xsize; x++, in += 2)
+ *out++ = in[0] + ((int) in[1] << 8);
+}
+
+static void
+i162l(UINT8* out, const UINT8* in, int xsize)
+{
+ int x;
+ for (x = 0; x < xsize; x++, in += 2)
+ if (in[1] != 0)
+ *out++ = 255;
+ else
+ *out++ = in[0];
+}
+
+static void
+i16b2i(UINT8* out_, const UINT8* in, int xsize)
+{
+ int x;
+ INT32* out = (INT32*) out_;
+ for (x = 0; x < xsize; x++, in += 2)
+ *out++ = ((int) in[0] << 8) + in[1];
+}
+
+
+static struct {
+ const char* from;
+ const char* to;
+ ImagingShuffler convert;
+} converters[] = {
+
+ { "1", "L", bit2l },
+ { "1", "I", bit2i },
+ { "1", "F", bit2f },
+ { "1", "RGB", bit2rgb },
+ { "1", "RGBA", bit2rgb },
+ { "1", "RGBX", bit2rgb },
+ { "1", "CMYK", bit2cmyk },
+ { "1", "YCbCr", bit2ycbcr },
+
+ { "L", "1", l2bit },
+ { "L", "LA", l2la },
+ { "L", "I", l2i },
+ { "L", "F", l2f },
+ { "L", "RGB", l2rgb },
+ { "L", "RGBA", l2rgb },
+ { "L", "RGBX", l2rgb },
+ { "L", "CMYK", l2cmyk },
+ { "L", "YCbCr", l2ycbcr },
+
+ { "LA", "L", la2l },
+ { "LA", "RGB", la2rgb },
+ { "LA", "RGBX", la2rgb },
+ { "LA", "RGBA", la2rgb },
+
+ { "I", "L", i2l },
+ { "I", "F", i2f },
+
+ { "F", "L", f2l },
+ { "F", "I", f2i },
+
+ { "RGB", "1", rgb2bit },
+ { "RGB", "L", rgb2l },
+ { "RGB", "LA", rgb2la },
+ { "RGB", "I", rgb2i },
+ { "RGB", "F", rgb2f },
+ { "RGB", "BGR;15", rgb2bgr15 },
+ { "RGB", "BGR;16", rgb2bgr16 },
+ { "RGB", "BGR;24", rgb2bgr24 },
+ { "RGB", "RGBA", rgb2rgba },
+ { "RGB", "RGBX", rgb2rgba },
+ { "RGB", "CMYK", rgb2cmyk },
+ { "RGB", "YCbCr", ImagingConvertRGB2YCbCr },
+
+ { "RGBA", "1", rgb2bit },
+ { "RGBA", "L", rgb2l },
+ { "RGBA", "LA", rgba2la },
+ { "RGBA", "I", rgb2i },
+ { "RGBA", "F", rgb2f },
+ { "RGBA", "RGB", rgba2rgb },
+ { "RGBA", "RGBa", rgba2rgba },
+ { "RGBA", "RGBX", rgb2rgba },
+ { "RGBA", "CMYK", rgb2cmyk },
+ { "RGBA", "YCbCr", ImagingConvertRGB2YCbCr },
+
+ { "RGBX", "1", rgb2bit },
+ { "RGBX", "L", rgb2l },
+ { "RGBA", "I", rgb2i },
+ { "RGBA", "F", rgb2f },
+ { "RGBX", "RGB", rgba2rgb },
+ { "RGBX", "CMYK", rgb2cmyk },
+ { "RGBX", "YCbCr", ImagingConvertRGB2YCbCr },
+
+ { "CMYK", "RGB", cmyk2rgb },
+ { "CMYK", "RGBA", cmyk2rgb },
+ { "CMYK", "RGBX", cmyk2rgb },
+
+ { "YCbCr", "L", ycbcr2l },
+ { "YCbCr", "RGB", ImagingConvertYCbCr2RGB },
+
+ { "I", "I;16", i2i16 },
+ { "I;16", "I", i162i },
+ { "I", "I;16B", i2i16b },
+ { "I;16B", "I", i16b2i },
+
+ { "L", "I;16", l2i16 },
+ { "I;16", "L", i162l },
+
+ { NULL }
+};
+
+/* FIXME: translate indexed versions to pointer versions below this line */
+
+/* ------------------- */
+/* Palette conversions */
+/* ------------------- */
+
+static void
+p2bit(UINT8* out, const UINT8* in, int xsize, const UINT8* palette)
+{
+ int x;
+ /* FIXME: precalculate greyscale palette? */
+ for (x = 0; x < xsize; x++)
+ *out++ = (L(&palette[in[x]*4]) >= 128000) ? 255 : 0;
+}
+
+static void
+p2l(UINT8* out, const UINT8* in, int xsize, const UINT8* palette)
+{
+ int x;
+ /* FIXME: precalculate greyscale palette? */
+ for (x = 0; x < xsize; x++)
+ *out++ = L(&palette[in[x]*4]) / 1000;
+}
+
+static void
+pa2la(UINT8* out, const UINT8* in, int xsize, const UINT8* palette)
+{
+ int x;
+ /* FIXME: precalculate greyscale palette? */
+ for (x = 0; x < xsize; x++, in += 2) {
+ *out++ = L(&palette[in[0]*4]) / 1000;
+ *out++ = in[1];
+ }
+}
+
+static void
+p2i(UINT8* out_, const UINT8* in, int xsize, const UINT8* palette)
+{
+ int x;
+ INT32* out = (INT32*) out_;
+ for (x = 0; x < xsize; x++)
+ *out++ = L(&palette[in[x]*4]) / 1000;
+}
+
+static void
+p2f(UINT8* out_, const UINT8* in, int xsize, const UINT8* palette)
+{
+ int x;
+ FLOAT32* out = (FLOAT32*) out_;
+ for (x = 0; x < xsize; x++)
+ *out++ = L(&palette[in[x]*4]) / 1000.0F;
+}
+
+static void
+p2rgb(UINT8* out, const UINT8* in, int xsize, const UINT8* palette)
+{
+ int x;
+ for (x = 0; x < xsize; x++) {
+ const UINT8* rgb = &palette[*in++ * 4];
+ *out++ = rgb[0];
+ *out++ = rgb[1];
+ *out++ = rgb[2];
+ *out++ = 255;
+ }
+}
+
+static void
+p2rgba(UINT8* out, const UINT8* in, int xsize, const UINT8* palette)
+{
+ int x;
+ for (x = 0; x < xsize; x++) {
+ const UINT8* rgba = &palette[*in++ * 4];
+ *out++ = rgba[0];
+ *out++ = rgba[1];
+ *out++ = rgba[2];
+ *out++ = rgba[3];
+ }
+}
+
+static void
+pa2rgba(UINT8* out, const UINT8* in, int xsize, const UINT8* palette)
+{
+ int x;
+ for (x = 0; x < xsize; x++, in += 4) {
+ const UINT8* rgb = &palette[in[0] * 4];
+ *out++ = rgb[0];
+ *out++ = rgb[1];
+ *out++ = rgb[2];
+ *out++ = in[3];
+ }
+}
+
+static void
+p2cmyk(UINT8* out, const UINT8* in, int xsize, const UINT8* palette)
+{
+ p2rgb(out, in, xsize, palette);
+ rgb2cmyk(out, out, xsize);
+}
+
+static void
+p2ycbcr(UINT8* out, const UINT8* in, int xsize, const UINT8* palette)
+{
+ p2rgb(out, in, xsize, palette);
+ ImagingConvertRGB2YCbCr(out, out, xsize);
+}
+
+static Imaging
+frompalette(Imaging imOut, Imaging imIn, const char *mode)
+{
+ ImagingSectionCookie cookie;
+ int alpha;
+ int y;
+ void (*convert)(UINT8*, const UINT8*, int, const UINT8*);
+
+ /* Map palette image to L, RGB, RGBA, or CMYK */
+
+ if (!imIn->palette)
+ return (Imaging) ImagingError_ValueError("no palette");
+
+ alpha = !strcmp(imIn->mode, "PA");
+
+ if (strcmp(mode, "1") == 0)
+ convert = p2bit;
+ else if (strcmp(mode, "L") == 0)
+ convert = p2l;
+ else if (strcmp(mode, "LA") == 0)
+ convert = (alpha) ? pa2la : p2l;
+ else if (strcmp(mode, "I") == 0)
+ convert = p2i;
+ else if (strcmp(mode, "F") == 0)
+ convert = p2f;
+ else if (strcmp(mode, "RGB") == 0)
+ convert = p2rgb;
+ else if (strcmp(mode, "RGBA") == 0)
+ convert = (alpha) ? pa2rgba : p2rgba;
+ else if (strcmp(mode, "RGBX") == 0)
+ convert = p2rgba;
+ else if (strcmp(mode, "CMYK") == 0)
+ convert = p2cmyk;
+ else if (strcmp(mode, "YCbCr") == 0)
+ convert = p2ycbcr;
+ else
+ return (Imaging) ImagingError_ValueError("conversion not supported");
+
+ imOut = ImagingNew2(mode, imOut, imIn);
+ if (!imOut)
+ return NULL;
+
+ ImagingSectionEnter(&cookie);
+ for (y = 0; y < imIn->ysize; y++)
+ (*convert)((UINT8*) imOut->image[y], (UINT8*) imIn->image[y],
+ imIn->xsize, imIn->palette->palette);
+ ImagingSectionLeave(&cookie);
+
+ return imOut;
+}
+
+static Imaging
+topalette(Imaging imOut, Imaging imIn, ImagingPalette inpalette, int dither)
+{
+ ImagingSectionCookie cookie;
+ int x, y;
+ ImagingPalette palette = inpalette;;
+
+ /* Map L or RGB/RGBX/RGBA to palette image */
+ if (strcmp(imIn->mode, "L") != 0 && strncmp(imIn->mode, "RGB", 3) != 0)
+ return (Imaging) ImagingError_ValueError("conversion not supported");
+
+ if (palette == NULL) {
+ /* FIXME: make user configurable */
+ if (imIn->bands == 1)
+ palette = ImagingPaletteNew("RGB"); /* Initialised to grey ramp */
+ else
+ palette = ImagingPaletteNewBrowser(); /* Standard colour cube */
+ }
+
+ if (!palette)
+ return (Imaging) ImagingError_ValueError("no palette");
+
+ imOut = ImagingNew2("P", imOut, imIn);
+ if (!imOut) {
+ if (palette != inpalette)
+ ImagingPaletteDelete(palette);
+ return NULL;
+ }
+
+ ImagingPaletteDelete(imOut->palette);
+ imOut->palette = ImagingPaletteDuplicate(palette);
+
+ if (imIn->bands == 1) {
+ /* greyscale image */
+
+ /* Greyscale palette: copy data as is */
+ ImagingSectionEnter(&cookie);
+ for (y = 0; y < imIn->ysize; y++)
+ memcpy(imOut->image[y], imIn->image[y], imIn->linesize);
+ ImagingSectionLeave(&cookie);
+
+ } else {
+ /* colour image */
+
+ /* Create mapping cache */
+ if (ImagingPaletteCachePrepare(palette) < 0) {
+ ImagingDelete(imOut);
+ if (palette != inpalette)
+ ImagingPaletteDelete(palette);
+ return NULL;
+ }
+
+ if (dither) {
+ /* floyd-steinberg dither */
+
+ int* errors;
+ errors = calloc(imIn->xsize + 1, sizeof(int) * 3);
+ if (!errors) {
+ ImagingDelete(imOut);
+ ImagingError_MemoryError();
+ return NULL;
+ }
+
+ /* Map each pixel to the nearest palette entry */
+ ImagingSectionEnter(&cookie);
+ for (y = 0; y < imIn->ysize; y++) {
+ int r, r0, r1, r2;
+ int g, g0, g1, g2;
+ int b, b0, b1, b2;
+ UINT8* in = (UINT8*) imIn->image[y];
+ UINT8* out = imOut->image8[y];
+ int* e = errors;
+
+ r = r0 = r1 = 0;
+ g = g0 = g1 = 0;
+ b = b0 = b1 = b2 = 0;
+
+ for (x = 0; x < imIn->xsize; x++, in += 4) {
+ int d2;
+ INT16* cache;
+
+ r = CLIP(in[0] + (r + e[3+0])/16);
+ g = CLIP(in[1] + (g + e[3+1])/16);
+ b = CLIP(in[2] + (b + e[3+2])/16);
+
+ /* get closest colour */
+ cache = &ImagingPaletteCache(palette, r, g, b);
+ if (cache[0] == 0x100)
+ ImagingPaletteCacheUpdate(palette, r, g, b);
+ out[x] = (UINT8) cache[0];
+
+ r -= (int) palette->palette[cache[0]*4];
+ g -= (int) palette->palette[cache[0]*4+1];
+ b -= (int) palette->palette[cache[0]*4+2];
+
+ /* propagate errors (don't ask ;-) */
+ r2 = r; d2 = r + r; r += d2; e[0] = r + r0;
+ r += d2; r0 = r + r1; r1 = r2; r += d2;
+ g2 = g; d2 = g + g; g += d2; e[1] = g + g0;
+ g += d2; g0 = g + g1; g1 = g2; g += d2;
+ b2 = b; d2 = b + b; b += d2; e[2] = b + b0;
+ b += d2; b0 = b + b1; b1 = b2; b += d2;
+
+ e += 3;
+
+ }
+
+ e[0] = b0;
+ e[1] = b1;
+ e[2] = b2;
+
+ }
+ ImagingSectionLeave(&cookie);
+ free(errors);
+
+ } else {
+
+ /* closest colour */
+ ImagingSectionEnter(&cookie);
+ for (y = 0; y < imIn->ysize; y++) {
+ int r, g, b;
+ UINT8* in = (UINT8*) imIn->image[y];
+ UINT8* out = imOut->image8[y];
+
+ for (x = 0; x < imIn->xsize; x++, in += 4) {
+ INT16* cache;
+
+ r = in[0]; g = in[1]; b = in[2];
+
+ /* get closest colour */
+ cache = &ImagingPaletteCache(palette, r, g, b);
+ if (cache[0] == 0x100)
+ ImagingPaletteCacheUpdate(palette, r, g, b);
+ out[x] = (UINT8) cache[0];
+
+ }
+ }
+ ImagingSectionLeave(&cookie);
+
+ }
+ if (inpalette != palette)
+ ImagingPaletteCacheDelete(palette);
+ }
+
+ if (inpalette != palette)
+ ImagingPaletteDelete(palette);
+
+ return imOut;
+}
+
+static Imaging
+tobilevel(Imaging imOut, Imaging imIn, int dither)
+{
+ ImagingSectionCookie cookie;
+ int x, y;
+ int* errors;
+
+ /* Map L or RGB to dithered 1 image */
+ if (strcmp(imIn->mode, "L") != 0 && strcmp(imIn->mode, "RGB") != 0)
+ return (Imaging) ImagingError_ValueError("conversion not supported");
+
+ imOut = ImagingNew2("1", imOut, imIn);
+ if (!imOut)
+ return NULL;
+
+ errors = calloc(imIn->xsize + 1, sizeof(int));
+ if (!errors) {
+ ImagingDelete(imOut);
+ ImagingError_MemoryError();
+ return NULL;
+ }
+
+ if (imIn->bands == 1) {
+
+ /* map each pixel to black or white, using error diffusion */
+ ImagingSectionEnter(&cookie);
+ for (y = 0; y < imIn->ysize; y++) {
+ int l, l0, l1, l2, d2;
+ UINT8* in = (UINT8*) imIn->image[y];
+ UINT8* out = imOut->image8[y];
+
+ l = l0 = l1 = 0;
+
+ for (x = 0; x < imIn->xsize; x++) {
+
+ /* pick closest colour */
+ l = CLIP(in[x] + (l + errors[x+1])/16);
+ out[x] = (l > 128) ? 255 : 0;
+
+ /* propagate errors */
+ l -= (int) out[x];
+ l2 = l; d2 = l + l; l += d2; errors[x] = l + l0;
+ l += d2; l0 = l + l1; l1 = l2; l += d2;
+ }
+
+ errors[x] = l0;
+
+ }
+ ImagingSectionLeave(&cookie);
+
+ } else {
+
+ /* map each pixel to black or white, using error diffusion */
+ ImagingSectionEnter(&cookie);
+ for (y = 0; y < imIn->ysize; y++) {
+ int l, l0, l1, l2, d2;
+ UINT8* in = (UINT8*) imIn->image[y];
+ UINT8* out = imOut->image8[y];
+
+ l = l0 = l1 = 0;
+
+ for (x = 0; x < imIn->xsize; x++, in += 4) {
+
+ /* pick closest colour */
+ l = CLIP(L(in)/1000 + (l + errors[x+1])/16);
+ out[x] = (l > 128) ? 255 : 0;
+
+ /* propagate errors */
+ l -= (int) out[x];
+ l2 = l; d2 = l + l; l += d2; errors[x] = l + l0;
+ l += d2; l0 = l + l1; l1 = l2; l += d2;
+
+ }
+
+ errors[x] = l0;
+
+ }
+ ImagingSectionLeave(&cookie);
+ }
+
+ free(errors);
+
+ return imOut;
+}
+
+
+static Imaging
+convert(Imaging imOut, Imaging imIn, const char *mode,
+ ImagingPalette palette, int dither)
+{
+ ImagingSectionCookie cookie;
+ ImagingShuffler convert;
+ int y;
+
+ if (!imIn)
+ return (Imaging) ImagingError_ModeError();
+
+ if (!mode) {
+ /* Map palette image to full depth */
+ if (!imIn->palette)
+ return (Imaging) ImagingError_ModeError();
+ mode = imIn->palette->mode;
+ } else
+ /* Same mode? */
+ if (!strcmp(imIn->mode, mode))
+ return ImagingCopy2(imOut, imIn);
+
+
+ /* test for special conversions */
+
+ if (strcmp(imIn->mode, "P") == 0 || strcmp(imIn->mode, "PA") == 0)
+ return frompalette(imOut, imIn, mode);
+
+ if (strcmp(mode, "P") == 0)
+ return topalette(imOut, imIn, palette, dither);
+
+ if (dither && strcmp(mode, "1") == 0)
+ return tobilevel(imOut, imIn, dither);
+
+
+ /* standard conversion machinery */
+
+ convert = NULL;
+
+ for (y = 0; converters[y].from; y++)
+ if (!strcmp(imIn->mode, converters[y].from) &&
+ !strcmp(mode, converters[y].to)) {
+ convert = converters[y].convert;
+ break;
+ }
+
+ if (!convert)
+#ifdef notdef
+ return (Imaging) ImagingError_ValueError("conversion not supported");
+#else
+ {
+ static char buf[256];
+ sprintf(buf, "conversion from %s to %s not supported", imIn->mode, mode);
+ return (Imaging) ImagingError_ValueError(buf);
+ }
+#endif
+
+ imOut = ImagingNew2(mode, imOut, imIn);
+ if (!imOut)
+ return NULL;
+
+ ImagingSectionEnter(&cookie);
+ for (y = 0; y < imIn->ysize; y++)
+ (*convert)((UINT8*) imOut->image[y], (UINT8*) imIn->image[y],
+ imIn->xsize);
+ ImagingSectionLeave(&cookie);
+
+ return imOut;
+}
+
+Imaging
+ImagingConvert(Imaging imIn, const char *mode,
+ ImagingPalette palette, int dither)
+{
+ return convert(NULL, imIn, mode, palette, dither);
+}
+
+Imaging
+ImagingConvert2(Imaging imOut, Imaging imIn)
+{
+ return convert(imOut, imIn, imOut->mode, NULL, 0);
+}
diff --git a/Imaging/libImaging/ConvertYCbCr.c b/Imaging/libImaging/ConvertYCbCr.c
new file mode 100644
index 0000000..2d47807
--- /dev/null
+++ b/Imaging/libImaging/ConvertYCbCr.c
@@ -0,0 +1,387 @@
+/*
+ * The Python Imaging Library.
+ * $Id: ConvertYCbCr.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * code to convert YCbCr data
+ *
+ * history:
+ * 98-07-01 hk Created
+ *
+ * Copyright (c) Secret Labs AB 1998
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+#include "Imaging.h"
+
+/* JPEG/JFIF YCbCr conversions
+
+ Y = R * 0.29900 + G * 0.58700 + B * 0.11400
+ Cb = R * -0.16874 + G * -0.33126 + B * 0.50000 + 128
+ Cr = R * 0.50000 + G * -0.41869 + B * -0.08131 + 128
+
+ R = Y + + (Cr - 128) * 1.40200
+ G = Y + (Cb - 128) * -0.34414 + (Cr - 128) * -0.71414
+ B = Y + (Cb - 128) * 1.77200
+
+*/
+
+#define SCALE 6 /* bits */
+
+static INT16 Y_R[] = { 0, 19, 38, 57, 77, 96, 115, 134, 153, 172, 191,
+210, 230, 249, 268, 287, 306, 325, 344, 364, 383, 402, 421, 440, 459,
+478, 498, 517, 536, 555, 574, 593, 612, 631, 651, 670, 689, 708, 727,
+746, 765, 785, 804, 823, 842, 861, 880, 899, 919, 938, 957, 976, 995,
+1014, 1033, 1052, 1072, 1091, 1110, 1129, 1148, 1167, 1186, 1206,
+1225, 1244, 1263, 1282, 1301, 1320, 1340, 1359, 1378, 1397, 1416,
+1435, 1454, 1473, 1493, 1512, 1531, 1550, 1569, 1588, 1607, 1627,
+1646, 1665, 1684, 1703, 1722, 1741, 1761, 1780, 1799, 1818, 1837,
+1856, 1875, 1894, 1914, 1933, 1952, 1971, 1990, 2009, 2028, 2048,
+2067, 2086, 2105, 2124, 2143, 2162, 2182, 2201, 2220, 2239, 2258,
+2277, 2296, 2315, 2335, 2354, 2373, 2392, 2411, 2430, 2449, 2469,
+2488, 2507, 2526, 2545, 2564, 2583, 2602, 2622, 2641, 2660, 2679,
+2698, 2717, 2736, 2756, 2775, 2794, 2813, 2832, 2851, 2870, 2890,
+2909, 2928, 2947, 2966, 2985, 3004, 3023, 3043, 3062, 3081, 3100,
+3119, 3138, 3157, 3177, 3196, 3215, 3234, 3253, 3272, 3291, 3311,
+3330, 3349, 3368, 3387, 3406, 3425, 3444, 3464, 3483, 3502, 3521,
+3540, 3559, 3578, 3598, 3617, 3636, 3655, 3674, 3693, 3712, 3732,
+3751, 3770, 3789, 3808, 3827, 3846, 3865, 3885, 3904, 3923, 3942,
+3961, 3980, 3999, 4019, 4038, 4057, 4076, 4095, 4114, 4133, 4153,
+4172, 4191, 4210, 4229, 4248, 4267, 4286, 4306, 4325, 4344, 4363,
+4382, 4401, 4420, 4440, 4459, 4478, 4497, 4516, 4535, 4554, 4574,
+4593, 4612, 4631, 4650, 4669, 4688, 4707, 4727, 4746, 4765, 4784,
+4803, 4822, 4841, 4861, 4880 };
+
+static INT16 Y_G[] = { 0, 38, 75, 113, 150, 188, 225, 263, 301, 338,
+376, 413, 451, 488, 526, 564, 601, 639, 676, 714, 751, 789, 826, 864,
+902, 939, 977, 1014, 1052, 1089, 1127, 1165, 1202, 1240, 1277, 1315,
+1352, 1390, 1428, 1465, 1503, 1540, 1578, 1615, 1653, 1691, 1728,
+1766, 1803, 1841, 1878, 1916, 1954, 1991, 2029, 2066, 2104, 2141,
+2179, 2217, 2254, 2292, 2329, 2367, 2404, 2442, 2479, 2517, 2555,
+2592, 2630, 2667, 2705, 2742, 2780, 2818, 2855, 2893, 2930, 2968,
+3005, 3043, 3081, 3118, 3156, 3193, 3231, 3268, 3306, 3344, 3381,
+3419, 3456, 3494, 3531, 3569, 3607, 3644, 3682, 3719, 3757, 3794,
+3832, 3870, 3907, 3945, 3982, 4020, 4057, 4095, 4132, 4170, 4208,
+4245, 4283, 4320, 4358, 4395, 4433, 4471, 4508, 4546, 4583, 4621,
+4658, 4696, 4734, 4771, 4809, 4846, 4884, 4921, 4959, 4997, 5034,
+5072, 5109, 5147, 5184, 5222, 5260, 5297, 5335, 5372, 5410, 5447,
+5485, 5522, 5560, 5598, 5635, 5673, 5710, 5748, 5785, 5823, 5861,
+5898, 5936, 5973, 6011, 6048, 6086, 6124, 6161, 6199, 6236, 6274,
+6311, 6349, 6387, 6424, 6462, 6499, 6537, 6574, 6612, 6650, 6687,
+6725, 6762, 6800, 6837, 6875, 6913, 6950, 6988, 7025, 7063, 7100,
+7138, 7175, 7213, 7251, 7288, 7326, 7363, 7401, 7438, 7476, 7514,
+7551, 7589, 7626, 7664, 7701, 7739, 7777, 7814, 7852, 7889, 7927,
+7964, 8002, 8040, 8077, 8115, 8152, 8190, 8227, 8265, 8303, 8340,
+8378, 8415, 8453, 8490, 8528, 8566, 8603, 8641, 8678, 8716, 8753,
+8791, 8828, 8866, 8904, 8941, 8979, 9016, 9054, 9091, 9129, 9167,
+9204, 9242, 9279, 9317, 9354, 9392, 9430, 9467, 9505, 9542, 9580 };
+
+static INT16 Y_B[] = { 0, 7, 15, 22, 29, 36, 44, 51, 58, 66, 73, 80,
+88, 95, 102, 109, 117, 124, 131, 139, 146, 153, 161, 168, 175, 182,
+190, 197, 204, 212, 219, 226, 233, 241, 248, 255, 263, 270, 277, 285,
+292, 299, 306, 314, 321, 328, 336, 343, 350, 358, 365, 372, 379, 387,
+394, 401, 409, 416, 423, 430, 438, 445, 452, 460, 467, 474, 482, 489,
+496, 503, 511, 518, 525, 533, 540, 547, 554, 562, 569, 576, 584, 591,
+598, 606, 613, 620, 627, 635, 642, 649, 657, 664, 671, 679, 686, 693,
+700, 708, 715, 722, 730, 737, 744, 751, 759, 766, 773, 781, 788, 795,
+803, 810, 817, 824, 832, 839, 846, 854, 861, 868, 876, 883, 890, 897,
+905, 912, 919, 927, 934, 941, 948, 956, 963, 970, 978, 985, 992, 1000,
+1007, 1014, 1021, 1029, 1036, 1043, 1051, 1058, 1065, 1073, 1080,
+1087, 1094, 1102, 1109, 1116, 1124, 1131, 1138, 1145, 1153, 1160,
+1167, 1175, 1182, 1189, 1197, 1204, 1211, 1218, 1226, 1233, 1240,
+1248, 1255, 1262, 1270, 1277, 1284, 1291, 1299, 1306, 1313, 1321,
+1328, 1335, 1342, 1350, 1357, 1364, 1372, 1379, 1386, 1394, 1401,
+1408, 1415, 1423, 1430, 1437, 1445, 1452, 1459, 1466, 1474, 1481,
+1488, 1496, 1503, 1510, 1518, 1525, 1532, 1539, 1547, 1554, 1561,
+1569, 1576, 1583, 1591, 1598, 1605, 1612, 1620, 1627, 1634, 1642,
+1649, 1656, 1663, 1671, 1678, 1685, 1693, 1700, 1707, 1715, 1722,
+1729, 1736, 1744, 1751, 1758, 1766, 1773, 1780, 1788, 1795, 1802,
+1809, 1817, 1824, 1831, 1839, 1846, 1853, 1860 };
+
+static INT16 Cb_R[] = { 0, -10, -21, -31, -42, -53, -64, -75, -85,
+-96, -107, -118, -129, -139, -150, -161, -172, -183, -193, -204, -215,
+-226, -237, -247, -258, -269, -280, -291, -301, -312, -323, -334,
+-345, -355, -366, -377, -388, -399, -409, -420, -431, -442, -453,
+-463, -474, -485, -496, -507, -517, -528, -539, -550, -561, -571,
+-582, -593, -604, -615, -625, -636, -647, -658, -669, -679, -690,
+-701, -712, -723, -733, -744, -755, -766, -777, -787, -798, -809,
+-820, -831, -841, -852, -863, -874, -885, -895, -906, -917, -928,
+-939, -949, -960, -971, -982, -993, -1003, -1014, -1025, -1036, -1047,
+-1057, -1068, -1079, -1090, -1101, -1111, -1122, -1133, -1144, -1155,
+-1165, -1176, -1187, -1198, -1209, -1219, -1230, -1241, -1252, -1263,
+-1273, -1284, -1295, -1306, -1317, -1327, -1338, -1349, -1360, -1371,
+-1381, -1392, -1403, -1414, -1425, -1435, -1446, -1457, -1468, -1479,
+-1489, -1500, -1511, -1522, -1533, -1543, -1554, -1565, -1576, -1587,
+-1597, -1608, -1619, -1630, -1641, -1651, -1662, -1673, -1684, -1694,
+-1705, -1716, -1727, -1738, -1748, -1759, -1770, -1781, -1792, -1802,
+-1813, -1824, -1835, -1846, -1856, -1867, -1878, -1889, -1900, -1910,
+-1921, -1932, -1943, -1954, -1964, -1975, -1986, -1997, -2008, -2018,
+-2029, -2040, -2051, -2062, -2072, -2083, -2094, -2105, -2116, -2126,
+-2137, -2148, -2159, -2170, -2180, -2191, -2202, -2213, -2224, -2234,
+-2245, -2256, -2267, -2278, -2288, -2299, -2310, -2321, -2332, -2342,
+-2353, -2364, -2375, -2386, -2396, -2407, -2418, -2429, -2440, -2450,
+-2461, -2472, -2483, -2494, -2504, -2515, -2526, -2537, -2548, -2558,
+-2569, -2580, -2591, -2602, -2612, -2623, -2634, -2645, -2656, -2666,
+-2677, -2688, -2699, -2710, -2720, -2731, -2742, -2753 };
+
+static INT16 Cb_G[] = { 0, -20, -41, -63, -84, -105, -126, -147, -169,
+-190, -211, -232, -253, -275, -296, -317, -338, -359, -381, -402,
+-423, -444, -465, -487, -508, -529, -550, -571, -593, -614, -635,
+-656, -677, -699, -720, -741, -762, -783, -805, -826, -847, -868,
+-889, -911, -932, -953, -974, -995, -1017, -1038, -1059, -1080, -1101,
+-1123, -1144, -1165, -1186, -1207, -1229, -1250, -1271, -1292, -1313,
+-1335, -1356, -1377, -1398, -1419, -1441, -1462, -1483, -1504, -1525,
+-1547, -1568, -1589, -1610, -1631, -1653, -1674, -1695, -1716, -1737,
+-1759, -1780, -1801, -1822, -1843, -1865, -1886, -1907, -1928, -1949,
+-1971, -1992, -2013, -2034, -2055, -2077, -2098, -2119, -2140, -2161,
+-2183, -2204, -2225, -2246, -2267, -2289, -2310, -2331, -2352, -2373,
+-2395, -2416, -2437, -2458, -2479, -2501, -2522, -2543, -2564, -2585,
+-2607, -2628, -2649, -2670, -2691, -2713, -2734, -2755, -2776, -2797,
+-2819, -2840, -2861, -2882, -2903, -2925, -2946, -2967, -2988, -3009,
+-3031, -3052, -3073, -3094, -3115, -3137, -3158, -3179, -3200, -3221,
+-3243, -3264, -3285, -3306, -3328, -3349, -3370, -3391, -3412, -3434,
+-3455, -3476, -3497, -3518, -3540, -3561, -3582, -3603, -3624, -3646,
+-3667, -3688, -3709, -3730, -3752, -3773, -3794, -3815, -3836, -3858,
+-3879, -3900, -3921, -3942, -3964, -3985, -4006, -4027, -4048, -4070,
+-4091, -4112, -4133, -4154, -4176, -4197, -4218, -4239, -4260, -4282,
+-4303, -4324, -4345, -4366, -4388, -4409, -4430, -4451, -4472, -4494,
+-4515, -4536, -4557, -4578, -4600, -4621, -4642, -4663, -4684, -4706,
+-4727, -4748, -4769, -4790, -4812, -4833, -4854, -4875, -4896, -4918,
+-4939, -4960, -4981, -5002, -5024, -5045, -5066, -5087, -5108, -5130,
+-5151, -5172, -5193, -5214, -5236, -5257, -5278, -5299, -5320, -5342,
+-5363, -5384, -5405 };
+
+static INT16 Cb_B[] = { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288,
+320, 352, 384, 416, 448, 480, 512, 544, 576, 608, 640, 672, 704, 736,
+768, 800, 832, 864, 896, 928, 960, 992, 1024, 1056, 1088, 1120, 1152,
+1184, 1216, 1248, 1280, 1312, 1344, 1376, 1408, 1440, 1472, 1504,
+1536, 1568, 1600, 1632, 1664, 1696, 1728, 1760, 1792, 1824, 1856,
+1888, 1920, 1952, 1984, 2016, 2048, 2080, 2112, 2144, 2176, 2208,
+2240, 2272, 2304, 2336, 2368, 2400, 2432, 2464, 2496, 2528, 2560,
+2592, 2624, 2656, 2688, 2720, 2752, 2784, 2816, 2848, 2880, 2912,
+2944, 2976, 3008, 3040, 3072, 3104, 3136, 3168, 3200, 3232, 3264,
+3296, 3328, 3360, 3392, 3424, 3456, 3488, 3520, 3552, 3584, 3616,
+3648, 3680, 3712, 3744, 3776, 3808, 3840, 3872, 3904, 3936, 3968,
+4000, 4032, 4064, 4096, 4128, 4160, 4192, 4224, 4256, 4288, 4320,
+4352, 4384, 4416, 4448, 4480, 4512, 4544, 4576, 4608, 4640, 4672,
+4704, 4736, 4768, 4800, 4832, 4864, 4896, 4928, 4960, 4992, 5024,
+5056, 5088, 5120, 5152, 5184, 5216, 5248, 5280, 5312, 5344, 5376,
+5408, 5440, 5472, 5504, 5536, 5568, 5600, 5632, 5664, 5696, 5728,
+5760, 5792, 5824, 5856, 5888, 5920, 5952, 5984, 6016, 6048, 6080,
+6112, 6144, 6176, 6208, 6240, 6272, 6304, 6336, 6368, 6400, 6432,
+6464, 6496, 6528, 6560, 6592, 6624, 6656, 6688, 6720, 6752, 6784,
+6816, 6848, 6880, 6912, 6944, 6976, 7008, 7040, 7072, 7104, 7136,
+7168, 7200, 7232, 7264, 7296, 7328, 7360, 7392, 7424, 7456, 7488,
+7520, 7552, 7584, 7616, 7648, 7680, 7712, 7744, 7776, 7808, 7840,
+7872, 7904, 7936, 7968, 8000, 8032, 8064, 8096, 8128, 8160 };
+
+#define Cr_R Cb_B
+
+static INT16 Cr_G[] = { 0, -26, -53, -79, -106, -133, -160, -187,
+-213, -240, -267, -294, -321, -347, -374, -401, -428, -455, -481,
+-508, -535, -562, -589, -615, -642, -669, -696, -722, -749, -776,
+-803, -830, -856, -883, -910, -937, -964, -990, -1017, -1044, -1071,
+-1098, -1124, -1151, -1178, -1205, -1232, -1258, -1285, -1312, -1339,
+-1366, -1392, -1419, -1446, -1473, -1500, -1526, -1553, -1580, -1607,
+-1634, -1660, -1687, -1714, -1741, -1768, -1794, -1821, -1848, -1875,
+-1902, -1928, -1955, -1982, -2009, -2036, -2062, -2089, -2116, -2143,
+-2169, -2196, -2223, -2250, -2277, -2303, -2330, -2357, -2384, -2411,
+-2437, -2464, -2491, -2518, -2545, -2571, -2598, -2625, -2652, -2679,
+-2705, -2732, -2759, -2786, -2813, -2839, -2866, -2893, -2920, -2947,
+-2973, -3000, -3027, -3054, -3081, -3107, -3134, -3161, -3188, -3215,
+-3241, -3268, -3295, -3322, -3349, -3375, -3402, -3429, -3456, -3483,
+-3509, -3536, -3563, -3590, -3616, -3643, -3670, -3697, -3724, -3750,
+-3777, -3804, -3831, -3858, -3884, -3911, -3938, -3965, -3992, -4018,
+-4045, -4072, -4099, -4126, -4152, -4179, -4206, -4233, -4260, -4286,
+-4313, -4340, -4367, -4394, -4420, -4447, -4474, -4501, -4528, -4554,
+-4581, -4608, -4635, -4662, -4688, -4715, -4742, -4769, -4796, -4822,
+-4849, -4876, -4903, -4929, -4956, -4983, -5010, -5037, -5063, -5090,
+-5117, -5144, -5171, -5197, -5224, -5251, -5278, -5305, -5331, -5358,
+-5385, -5412, -5439, -5465, -5492, -5519, -5546, -5573, -5599, -5626,
+-5653, -5680, -5707, -5733, -5760, -5787, -5814, -5841, -5867, -5894,
+-5921, -5948, -5975, -6001, -6028, -6055, -6082, -6109, -6135, -6162,
+-6189, -6216, -6243, -6269, -6296, -6323, -6350, -6376, -6403, -6430,
+-6457, -6484, -6510, -6537, -6564, -6591, -6618, -6644, -6671, -6698,
+-6725, -6752, -6778, -6805, -6832 };
+
+static INT16 Cr_B[] = { 0, -4, -9, -15, -20, -25, -30, -35, -41, -46,
+-51, -56, -61, -67, -72, -77, -82, -87, -93, -98, -103, -108, -113,
+-119, -124, -129, -134, -140, -145, -150, -155, -160, -166, -171,
+-176, -181, -186, -192, -197, -202, -207, -212, -218, -223, -228,
+-233, -238, -244, -249, -254, -259, -264, -270, -275, -280, -285,
+-290, -296, -301, -306, -311, -316, -322, -327, -332, -337, -342,
+-348, -353, -358, -363, -368, -374, -379, -384, -389, -394, -400,
+-405, -410, -415, -421, -426, -431, -436, -441, -447, -452, -457,
+-462, -467, -473, -478, -483, -488, -493, -499, -504, -509, -514,
+-519, -525, -530, -535, -540, -545, -551, -556, -561, -566, -571,
+-577, -582, -587, -592, -597, -603, -608, -613, -618, -623, -629,
+-634, -639, -644, -649, -655, -660, -665, -670, -675, -681, -686,
+-691, -696, -702, -707, -712, -717, -722, -728, -733, -738, -743,
+-748, -754, -759, -764, -769, -774, -780, -785, -790, -795, -800,
+-806, -811, -816, -821, -826, -832, -837, -842, -847, -852, -858,
+-863, -868, -873, -878, -884, -889, -894, -899, -904, -910, -915,
+-920, -925, -930, -936, -941, -946, -951, -957, -962, -967, -972,
+-977, -983, -988, -993, -998, -1003, -1009, -1014, -1019, -1024,
+-1029, -1035, -1040, -1045, -1050, -1055, -1061, -1066, -1071, -1076,
+-1081, -1087, -1092, -1097, -1102, -1107, -1113, -1118, -1123, -1128,
+-1133, -1139, -1144, -1149, -1154, -1159, -1165, -1170, -1175, -1180,
+-1185, -1191, -1196, -1201, -1206, -1211, -1217, -1222, -1227, -1232,
+-1238, -1243, -1248, -1253, -1258, -1264, -1269, -1274, -1279, -1284,
+-1290, -1295, -1300, -1305, -1310, -1316, -1321, -1326 };
+
+static INT16 R_Cr[] = { -11484, -11394, -11305, -11215, -11125,
+-11036, -10946, -10856, -10766, -10677, -10587, -10497, -10407,
+-10318, -10228, -10138, -10049, -9959, -9869, -9779, -9690, -9600,
+-9510, -9420, -9331, -9241, -9151, -9062, -8972, -8882, -8792, -8703,
+-8613, -8523, -8433, -8344, -8254, -8164, -8075, -7985, -7895, -7805,
+-7716, -7626, -7536, -7446, -7357, -7267, -7177, -7088, -6998, -6908,
+-6818, -6729, -6639, -6549, -6459, -6370, -6280, -6190, -6101, -6011,
+-5921, -5831, -5742, -5652, -5562, -5472, -5383, -5293, -5203, -5113,
+-5024, -4934, -4844, -4755, -4665, -4575, -4485, -4396, -4306, -4216,
+-4126, -4037, -3947, -3857, -3768, -3678, -3588, -3498, -3409, -3319,
+-3229, -3139, -3050, -2960, -2870, -2781, -2691, -2601, -2511, -2422,
+-2332, -2242, -2152, -2063, -1973, -1883, -1794, -1704, -1614, -1524,
+-1435, -1345, -1255, -1165, -1076, -986, -896, -807, -717, -627, -537,
+-448, -358, -268, -178, -89, 0, 90, 179, 269, 359, 449, 538, 628, 718,
+808, 897, 987, 1077, 1166, 1256, 1346, 1436, 1525, 1615, 1705, 1795,
+1884, 1974, 2064, 2153, 2243, 2333, 2423, 2512, 2602, 2692, 2782,
+2871, 2961, 3051, 3140, 3230, 3320, 3410, 3499, 3589, 3679, 3769,
+3858, 3948, 4038, 4127, 4217, 4307, 4397, 4486, 4576, 4666, 4756,
+4845, 4935, 5025, 5114, 5204, 5294, 5384, 5473, 5563, 5653, 5743,
+5832, 5922, 6012, 6102, 6191, 6281, 6371, 6460, 6550, 6640, 6730,
+6819, 6909, 6999, 7089, 7178, 7268, 7358, 7447, 7537, 7627, 7717,
+7806, 7896, 7986, 8076, 8165, 8255, 8345, 8434, 8524, 8614, 8704,
+8793, 8883, 8973, 9063, 9152, 9242, 9332, 9421, 9511, 9601, 9691,
+9780, 9870, 9960, 10050, 10139, 10229, 10319, 10408, 10498, 10588,
+10678, 10767, 10857, 10947, 11037, 11126, 11216, 11306, 11395 };
+
+static INT16 G_Cb[] = { 2819, 2797, 2775, 2753, 2731, 2709, 2687,
+2665, 2643, 2621, 2599, 2577, 2555, 2533, 2511, 2489, 2467, 2445,
+2423, 2401, 2379, 2357, 2335, 2313, 2291, 2269, 2247, 2225, 2202,
+2180, 2158, 2136, 2114, 2092, 2070, 2048, 2026, 2004, 1982, 1960,
+1938, 1916, 1894, 1872, 1850, 1828, 1806, 1784, 1762, 1740, 1718,
+1696, 1674, 1652, 1630, 1608, 1586, 1564, 1542, 1520, 1498, 1476,
+1454, 1432, 1410, 1388, 1366, 1344, 1321, 1299, 1277, 1255, 1233,
+1211, 1189, 1167, 1145, 1123, 1101, 1079, 1057, 1035, 1013, 991, 969,
+947, 925, 903, 881, 859, 837, 815, 793, 771, 749, 727, 705, 683, 661,
+639, 617, 595, 573, 551, 529, 507, 485, 463, 440, 418, 396, 374, 352,
+330, 308, 286, 264, 242, 220, 198, 176, 154, 132, 110, 88, 66, 44, 22,
+0, -21, -43, -65, -87, -109, -131, -153, -175, -197, -219, -241, -263,
+-285, -307, -329, -351, -373, -395, -417, -439, -462, -484, -506,
+-528, -550, -572, -594, -616, -638, -660, -682, -704, -726, -748,
+-770, -792, -814, -836, -858, -880, -902, -924, -946, -968, -990,
+-1012, -1034, -1056, -1078, -1100, -1122, -1144, -1166, -1188, -1210,
+-1232, -1254, -1276, -1298, -1320, -1343, -1365, -1387, -1409, -1431,
+-1453, -1475, -1497, -1519, -1541, -1563, -1585, -1607, -1629, -1651,
+-1673, -1695, -1717, -1739, -1761, -1783, -1805, -1827, -1849, -1871,
+-1893, -1915, -1937, -1959, -1981, -2003, -2025, -2047, -2069, -2091,
+-2113, -2135, -2157, -2179, -2201, -2224, -2246, -2268, -2290, -2312,
+-2334, -2356, -2378, -2400, -2422, -2444, -2466, -2488, -2510, -2532,
+-2554, -2576, -2598, -2620, -2642, -2664, -2686, -2708, -2730, -2752,
+-2774, -2796 };
+
+static INT16 G_Cr[] = { 5850, 5805, 5759, 5713, 5667, 5622, 5576,
+5530, 5485, 5439, 5393, 5347, 5302, 5256, 5210, 5165, 5119, 5073,
+5028, 4982, 4936, 4890, 4845, 4799, 4753, 4708, 4662, 4616, 4570,
+4525, 4479, 4433, 4388, 4342, 4296, 4251, 4205, 4159, 4113, 4068,
+4022, 3976, 3931, 3885, 3839, 3794, 3748, 3702, 3656, 3611, 3565,
+3519, 3474, 3428, 3382, 3336, 3291, 3245, 3199, 3154, 3108, 3062,
+3017, 2971, 2925, 2879, 2834, 2788, 2742, 2697, 2651, 2605, 2559,
+2514, 2468, 2422, 2377, 2331, 2285, 2240, 2194, 2148, 2102, 2057,
+2011, 1965, 1920, 1874, 1828, 1782, 1737, 1691, 1645, 1600, 1554,
+1508, 1463, 1417, 1371, 1325, 1280, 1234, 1188, 1143, 1097, 1051,
+1006, 960, 914, 868, 823, 777, 731, 686, 640, 594, 548, 503, 457, 411,
+366, 320, 274, 229, 183, 137, 91, 46, 0, -45, -90, -136, -182, -228,
+-273, -319, -365, -410, -456, -502, -547, -593, -639, -685, -730,
+-776, -822, -867, -913, -959, -1005, -1050, -1096, -1142, -1187,
+-1233, -1279, -1324, -1370, -1416, -1462, -1507, -1553, -1599, -1644,
+-1690, -1736, -1781, -1827, -1873, -1919, -1964, -2010, -2056, -2101,
+-2147, -2193, -2239, -2284, -2330, -2376, -2421, -2467, -2513, -2558,
+-2604, -2650, -2696, -2741, -2787, -2833, -2878, -2924, -2970, -3016,
+-3061, -3107, -3153, -3198, -3244, -3290, -3335, -3381, -3427, -3473,
+-3518, -3564, -3610, -3655, -3701, -3747, -3793, -3838, -3884, -3930,
+-3975, -4021, -4067, -4112, -4158, -4204, -4250, -4295, -4341, -4387,
+-4432, -4478, -4524, -4569, -4615, -4661, -4707, -4752, -4798, -4844,
+-4889, -4935, -4981, -5027, -5072, -5118, -5164, -5209, -5255, -5301,
+-5346, -5392, -5438, -5484, -5529, -5575, -5621, -5666, -5712, -5758,
+-5804 };
+
+static INT16 B_Cb[] = { -14515, -14402, -14288, -14175, -14062,
+-13948, -13835, -13721, -13608, -13495, -13381, -13268, -13154,
+-13041, -12928, -12814, -12701, -12587, -12474, -12360, -12247,
+-12134, -12020, -11907, -11793, -11680, -11567, -11453, -11340,
+-11226, -11113, -11000, -10886, -10773, -10659, -10546, -10433,
+-10319, -10206, -10092, -9979, -9865, -9752, -9639, -9525, -9412,
+-9298, -9185, -9072, -8958, -8845, -8731, -8618, -8505, -8391, -8278,
+-8164, -8051, -7938, -7824, -7711, -7597, -7484, -7371, -7257, -7144,
+-7030, -6917, -6803, -6690, -6577, -6463, -6350, -6236, -6123, -6010,
+-5896, -5783, -5669, -5556, -5443, -5329, -5216, -5102, -4989, -4876,
+-4762, -4649, -4535, -4422, -4309, -4195, -4082, -3968, -3855, -3741,
+-3628, -3515, -3401, -3288, -3174, -3061, -2948, -2834, -2721, -2607,
+-2494, -2381, -2267, -2154, -2040, -1927, -1814, -1700, -1587, -1473,
+-1360, -1246, -1133, -1020, -906, -793, -679, -566, -453, -339, -226,
+-112, 0, 113, 227, 340, 454, 567, 680, 794, 907, 1021, 1134, 1247,
+1361, 1474, 1588, 1701, 1815, 1928, 2041, 2155, 2268, 2382, 2495,
+2608, 2722, 2835, 2949, 3062, 3175, 3289, 3402, 3516, 3629, 3742,
+3856, 3969, 4083, 4196, 4310, 4423, 4536, 4650, 4763, 4877, 4990,
+5103, 5217, 5330, 5444, 5557, 5670, 5784, 5897, 6011, 6124, 6237,
+6351, 6464, 6578, 6691, 6804, 6918, 7031, 7145, 7258, 7372, 7485,
+7598, 7712, 7825, 7939, 8052, 8165, 8279, 8392, 8506, 8619, 8732,
+8846, 8959, 9073, 9186, 9299, 9413, 9526, 9640, 9753, 9866, 9980,
+10093, 10207, 10320, 10434, 10547, 10660, 10774, 10887, 11001, 11114,
+11227, 11341, 11454, 11568, 11681, 11794, 11908, 12021, 12135, 12248,
+12361, 12475, 12588, 12702, 12815, 12929, 13042, 13155, 13269, 13382,
+13496, 13609, 13722, 13836, 13949, 14063, 14176, 14289, 14403 };
+
+
+void
+ImagingConvertRGB2YCbCr(UINT8* out, const UINT8* in, int pixels)
+{
+ int x;
+ UINT8 a;
+ int r, g, b;
+ int y, cr, cb;
+
+ for (x = 0; x < pixels; x++, in +=4, out += 4) {
+
+ r = in[0];
+ g = in[1];
+ b = in[2];
+ a = in[3];
+
+ y = (Y_R[r] + Y_G[g] + Y_B[b]) >> SCALE;
+ cb = ((Cb_R[r] + Cb_G[g] + Cb_B[b]) >> SCALE) + 128;
+ cr = ((Cr_R[r] + Cr_G[g] + Cr_B[b]) >> SCALE) + 128;
+
+ out[0] = (UINT8) y;
+ out[1] = (UINT8) cb;
+ out[2] = (UINT8) cr;
+ out[3] = a;
+ }
+}
+
+void
+ImagingConvertYCbCr2RGB(UINT8* out, const UINT8* in, int pixels)
+{
+ int x;
+ UINT8 a;
+ int r, g, b;
+ int y, cr, cb;
+
+ for (x = 0; x < pixels; x++, in += 4, out += 4) {
+
+ y = in[0];
+ cb = in[1];
+ cr = in[2];
+ a = in[3];
+
+ r = y + (( R_Cr[cr]) >> SCALE);
+ g = y + ((G_Cb[cb] + G_Cr[cr]) >> SCALE);
+ b = y + ((B_Cb[cb] ) >> SCALE);
+
+ out[0] = (r <= 0) ? 0 : (r >= 255) ? 255 : r;
+ out[1] = (g <= 0) ? 0 : (g >= 255) ? 255 : g;
+ out[2] = (b <= 0) ? 0 : (b >= 255) ? 255 : b;
+ out[3] = a;
+ }
+}
diff --git a/Imaging/libImaging/Copy.c b/Imaging/libImaging/Copy.c
new file mode 100644
index 0000000..1d799b1
--- /dev/null
+++ b/Imaging/libImaging/Copy.c
@@ -0,0 +1,58 @@
+/*
+ * The Python Imaging Library
+ * $Id: Copy.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * copy image
+ *
+ * history:
+ * 95-11-26 fl Moved from Imaging.c
+ * 97-05-12 fl Added ImagingCopy2
+ * 97-08-28 fl Allow imOut == NULL in ImagingCopy2
+ *
+ * Copyright (c) Fredrik Lundh 1995-97.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for details on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+static Imaging
+_copy(Imaging imOut, Imaging imIn)
+{
+ ImagingSectionCookie cookie;
+ int y;
+
+ if (!imIn)
+ return (Imaging) ImagingError_ValueError(NULL);
+
+ imOut = ImagingNew2(imIn->mode, imOut, imIn);
+ if (!imOut)
+ return NULL;
+
+ ImagingCopyInfo(imOut, imIn);
+
+ ImagingSectionEnter(&cookie);
+ if (imIn->block != NULL && imOut->block != NULL)
+ memcpy(imOut->block, imIn->block, imIn->ysize * imIn->linesize);
+ else
+ for (y = 0; y < imIn->ysize; y++)
+ memcpy(imOut->image[y], imIn->image[y], imIn->linesize);
+ ImagingSectionLeave(&cookie);
+
+ return imOut;
+}
+
+Imaging
+ImagingCopy(Imaging imIn)
+{
+ return _copy(NULL, imIn);
+}
+
+Imaging
+ImagingCopy2(Imaging imOut, Imaging imIn)
+{
+ return _copy(imOut, imIn);
+}
diff --git a/Imaging/libImaging/Crc32.c b/Imaging/libImaging/Crc32.c
new file mode 100644
index 0000000..8d7922e
--- /dev/null
+++ b/Imaging/libImaging/Crc32.c
@@ -0,0 +1,87 @@
+/*
+ * The Python Imaging Library
+ * $Id: Crc32.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * calculate ISO 3307 checksum
+ *
+ * history:
+ * 96-12-10 fl: Created (based on example in the PNG spec)
+ *
+ * Copyright (c) Fredrik Lundh 1996.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+/* Precalculated CRC values (created by makecrctable.py) */
+
+static UINT32 crc32table[] = { 0x0, 0x77073096L, 0xEE0E612CL,
+0x990951BAL, 0x76DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
+0xEDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, 0x9B64C2BL,
+0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, 0x1DB71064L, 0x6AB020F2L,
+0xF3B97148L, 0x84BE41DEL, 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L,
+0x83D385C7L, 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL,
+0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, 0x3B6E20C8L,
+0x4C69105EL, 0xD56041E4L, 0xA2677172L, 0x3C03E4D1L, 0x4B04D447L,
+0xD20D85FDL, 0xA50AB56BL, 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L,
+0xACBCF940L, 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,
+0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, 0x21B4F4B5L,
+0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, 0x2802B89EL, 0x5F058808L,
+0xC60CD9B2L, 0xB10BE924L, 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL,
+0xB6662D3DL, 0x76DC4190L, 0x1DB7106L, 0x98D220BCL, 0xEFD5102AL,
+0x71B18589L, 0x6B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, 0x7807C9A2L,
+0xF00F934L, 0x9609A88EL, 0xE10E9818L, 0x7F6A0DBBL, 0x86D3D2DL,
+0x91646C97L, 0xE6635C01L, 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L,
+0xF262004EL, 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,
+0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, 0x62DD1DDFL,
+0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, 0x4DB26158L, 0x3AB551CEL,
+0xA3BC0074L, 0xD4BB30E2L, 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL,
+0xD3D6F4FBL, 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L,
+0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, 0x5005713CL,
+0x270241AAL, 0xBE0B1010L, 0xC90C2086L, 0x5768B525L, 0x206F85B3L,
+0xB966D409L, 0xCE61E49FL, 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L,
+0xC7D7A8B4L, 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,
+0xEDB88320L, 0x9ABFB3B6L, 0x3B6E20CL, 0x74B1D29AL, 0xEAD54739L,
+0x9DD277AFL, 0x4DB2615L, 0x73DC1683L, 0xE3630B12L, 0x94643B84L,
+0xD6D6A3EL, 0x7A6A5AA8L, 0xE40ECF0BL, 0x9309FF9DL, 0xA00AE27L,
+0x7D079EB1L, 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL,
+0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, 0xFED41B76L,
+0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, 0xF9B9DF6FL, 0x8EBEEFF9L,
+0x17B7BE43L, 0x60B08ED5L, 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L,
+0x4FDFF252L, 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL,
+0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, 0xDF60EFC3L,
+0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, 0xCB61B38CL, 0xBC66831AL,
+0x256FD2A0L, 0x5268E236L, 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L,
+0x5505262FL, 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L,
+0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, 0x9B64C2B0L,
+0xEC63F226L, 0x756AA39CL, 0x26D930AL, 0x9C0906A9L, 0xEB0E363FL,
+0x72076785L, 0x5005713L, 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL,
+0xCB61B38L, 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0xBDBDF21L,
+0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, 0x81BE16CDL,
+0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, 0x88085AE6L, 0xFF0F6A70L,
+0x66063BCAL, 0x11010B5CL, 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L,
+0x166CCF45L, 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L,
+0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, 0xAED16A4AL,
+0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, 0xA9BCAE53L, 0xDEBB9EC5L,
+0x47B2CF7FL, 0x30B5FFE9L, 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L,
+0x24B4A3A6L, 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,
+0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, 0xB40BBE37L,
+0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL };
+
+
+UINT32
+ImagingCRC32(UINT32 crc, UINT8* buffer, int bytes)
+{
+ int i;
+
+ crc ^= 0xFFFFFFFFL;
+
+ for (i = 0; i < bytes; i++)
+ crc = crc32table[(UINT8) crc ^ buffer[i]] ^ (crc >> 8);
+
+ return crc ^ 0xFFFFFFFFL;
+}
diff --git a/Imaging/libImaging/Crop.c b/Imaging/libImaging/Crop.c
new file mode 100644
index 0000000..8d3fd3b
--- /dev/null
+++ b/Imaging/libImaging/Crop.c
@@ -0,0 +1,57 @@
+/*
+ * The Python Imaging Library
+ * $Id: Crop.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * cut region from image
+ *
+ * history:
+ * 95-11-27 fl Created
+ * 98-07-10 fl Fixed "null result" error
+ * 99-02-05 fl Rewritten to use Paste primitive
+ *
+ * Copyright (c) Secret Labs AB 1997-99.
+ * Copyright (c) Fredrik Lundh 1995.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+Imaging
+ImagingCrop(Imaging imIn, int sx0, int sy0, int sx1, int sy1)
+{
+ Imaging imOut;
+ int xsize, ysize;
+ int dx0, dy0, dx1, dy1;
+
+ if (!imIn)
+ return (Imaging) ImagingError_ModeError();
+
+ xsize = sx1 - sx0;
+ if (xsize < 0)
+ xsize = 0;
+ ysize = sy1 - sy0;
+ if (ysize < 0)
+ ysize = 0;
+
+ imOut = ImagingNew(imIn->mode, xsize, ysize);
+ if (!imOut)
+ return NULL;
+
+ ImagingCopyInfo(imOut, imIn);
+
+ dx0 = -sx0;
+ dy0 = -sy0;
+ dx1 = imIn->xsize - sx0;
+ dy1 = imIn->ysize - sy0;
+
+ /* paste the source image on top of the output image!!! */
+ if (ImagingPaste(imOut, imIn, NULL, dx0, dy0, dx1, dy1) < 0) {
+ ImagingDelete(imOut);
+ return NULL;
+ }
+
+ return imOut;
+}
diff --git a/Imaging/libImaging/Dib.c b/Imaging/libImaging/Dib.c
new file mode 100644
index 0000000..597f6ef
--- /dev/null
+++ b/Imaging/libImaging/Dib.c
@@ -0,0 +1,311 @@
+/*
+ * The Python Imaging Library
+ * $Id: Dib.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * imaging display object for Windows
+ *
+ * history:
+ * 1996-05-12 fl Created
+ * 1996-05-17 fl Up and running
+ * 1996-05-21 fl Added palette stuff
+ * 1996-05-26 fl Added query palette and mode inquery
+ * 1997-09-21 fl Added draw primitive
+ * 1998-01-20 fl Use StretchDIBits instead of StretchBlt
+ * 1998-12-30 fl Plugged a resource leak in DeleteDIB (from Roger Burnham)
+ *
+ * Copyright (c) Secret Labs AB 1997-2001.
+ * Copyright (c) Fredrik Lundh 1996.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+#ifdef WIN32
+
+#include "ImDib.h"
+
+
+char*
+ImagingGetModeDIB(int size_out[2])
+{
+ /* Get device characteristics */
+
+ HDC dc;
+ char* mode;
+
+ dc = CreateCompatibleDC(NULL);
+
+ mode = "P";
+ if (!(GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE)) {
+ mode = "RGB";
+ if (GetDeviceCaps(dc, BITSPIXEL) == 1)
+ mode = "1";
+ }
+
+ if (size_out) {
+ size_out[0] = GetDeviceCaps(dc, HORZRES);
+ size_out[1] = GetDeviceCaps(dc, VERTRES);
+ }
+
+ DeleteDC(dc);
+
+ return mode;
+}
+
+
+ImagingDIB
+ImagingNewDIB(const char *mode, int xsize, int ysize)
+{
+ /* Create a Windows bitmap */
+
+ ImagingDIB dib;
+ RGBQUAD *palette;
+ int i;
+
+ /* Check mode */
+ if (strcmp(mode, "1") != 0 && strcmp(mode, "L") != 0 &&
+ strcmp(mode, "RGB") != 0)
+ return (ImagingDIB) ImagingError_ModeError();
+
+ /* Create DIB context and info header */
+ dib = (ImagingDIB) malloc(sizeof(*dib));
+ if (!dib)
+ return (ImagingDIB) ImagingError_MemoryError();
+ dib->info = (BITMAPINFO*) malloc(sizeof(BITMAPINFOHEADER) +
+ 256 * sizeof(RGBQUAD));
+ if (!dib->info) {
+ free(dib);
+ return (ImagingDIB) ImagingError_MemoryError();
+ }
+
+ memset(dib->info, 0, sizeof(BITMAPINFOHEADER));
+ dib->info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ dib->info->bmiHeader.biWidth = xsize;
+ dib->info->bmiHeader.biHeight = ysize;
+ dib->info->bmiHeader.biPlanes = 1;
+ dib->info->bmiHeader.biBitCount = strlen(mode)*8;
+ dib->info->bmiHeader.biCompression = BI_RGB;
+
+ /* Create DIB */
+ dib->dc = CreateCompatibleDC(NULL);
+ if (!dib->dc) {
+ free(dib->info);
+ free(dib);
+ return (ImagingDIB) ImagingError_MemoryError();
+ }
+
+ dib->bitmap = CreateDIBSection(dib->dc, dib->info, DIB_RGB_COLORS,
+ &dib->bits, NULL, 0);
+ if (!dib->bitmap) {
+ free(dib->info);
+ free(dib);
+ return (ImagingDIB) ImagingError_MemoryError();
+ }
+
+ strcpy(dib->mode, mode);
+ dib->xsize = xsize;
+ dib->ysize = ysize;
+
+ dib->pixelsize = strlen(mode);
+ dib->linesize = (xsize * dib->pixelsize + 3) & -4;
+
+ if (dib->pixelsize == 1)
+ dib->pack = dib->unpack = (ImagingShuffler) memcpy;
+ else {
+ dib->pack = ImagingPackBGR;
+ dib->unpack = ImagingPackBGR;
+ }
+
+ /* Bind the DIB to the device context */
+ dib->old_bitmap = SelectObject(dib->dc, dib->bitmap);
+
+ palette = dib->info->bmiColors;
+
+ /* Bind a palette to it as well (only required for 8-bit DIBs) */
+ if (dib->pixelsize == 1) {
+ for (i = 0; i < 256; i++) {
+ palette[i].rgbRed =
+ palette[i].rgbGreen =
+ palette[i].rgbBlue = i;
+ palette[i].rgbReserved = 0;
+ }
+ SetDIBColorTable(dib->dc, 0, 256, palette);
+ }
+
+ /* Create an associated palette (for 8-bit displays only) */
+ if (strcmp(ImagingGetModeDIB(NULL), "P") == 0) {
+
+ char palbuf[sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY)];
+ LPLOGPALETTE pal = (LPLOGPALETTE) palbuf;
+ int i, r, g, b;
+
+ /* Load system palette */
+ pal->palVersion = 0x300;
+ pal->palNumEntries = 256;
+ GetSystemPaletteEntries(dib->dc, 0, 256, pal->palPalEntry);
+
+ if (strcmp(mode, "L") == 0) {
+
+ /* Greyscale DIB. Fill all 236 slots with a greyscale ramp
+ * (this is usually overkill on Windows since VGA only offers
+ * 6 bits greyscale resolution). Ignore the slots already
+ * allocated by Windows */
+
+ i = 10;
+ for (r = 0; r < 236; r++) {
+ pal->palPalEntry[i].peRed =
+ pal->palPalEntry[i].peGreen =
+ pal->palPalEntry[i].peBlue = i;
+ i++;
+ }
+
+ dib->palette = CreatePalette(pal);
+
+ } else if (strcmp(mode, "RGB") == 0) {
+
+#ifdef CUBE216
+
+ /* Colour DIB. Create a 6x6x6 colour cube (216 entries) and
+ * add 20 extra greylevels for best result with greyscale
+ * images. */
+
+ i = 10;
+ for (r = 0; r < 256; r += 51)
+ for (g = 0; g < 256; g += 51)
+ for (b = 0; b < 256; b += 51) {
+ pal->palPalEntry[i].peRed = r;
+ pal->palPalEntry[i].peGreen = g;
+ pal->palPalEntry[i].peBlue = b;
+ i++;
+ }
+ for (r = 1; r < 22-1; r++) {
+ /* Black and white are already provided by the cube. */
+ pal->palPalEntry[i].peRed =
+ pal->palPalEntry[i].peGreen =
+ pal->palPalEntry[i].peBlue = r * 255 / (22-1);
+ i++;
+ }
+
+#else
+
+ /* Colour DIB. Alternate palette. */
+
+ i = 10;
+ for (r = 0; r < 256; r += 37)
+ for (g = 0; g < 256; g += 32)
+ for (b = 0; b < 256; b += 64) {
+ pal->palPalEntry[i].peRed = r;
+ pal->palPalEntry[i].peGreen = g;
+ pal->palPalEntry[i].peBlue = b;
+ i++;
+ }
+
+#endif
+
+#if 0
+ {
+ /* DEBUG: dump palette to file */
+ FILE *err = fopen("dib.pal", "w");
+ for (i = 0; i < 256; i++)
+ fprintf(err, "%d: %d/%d/%d\n", i,
+ pal->palPalEntry[i].peRed,
+ pal->palPalEntry[i].peGreen,
+ pal->palPalEntry[i].peBlue);
+ fclose(err);
+ }
+#endif
+
+ dib->palette = CreatePalette(pal);
+
+ }
+
+ }
+
+ return dib;
+}
+
+void
+ImagingPasteDIB(ImagingDIB dib, Imaging im, int xy[4])
+{
+ /* Paste image data into a bitmap */
+
+ /* FIXME: check size! */
+
+ int y;
+ for (y = 0; y < im->ysize; y++)
+ dib->pack(dib->bits + dib->linesize*(dib->ysize-(xy[1]+y)-1) +
+ xy[0]*dib->pixelsize, im->image[y], im->xsize);
+
+}
+
+void
+ImagingExposeDIB(ImagingDIB dib, int dc)
+{
+ /* Copy bitmap to display */
+
+ if (dib->palette != 0)
+ SelectPalette((HDC) dc, dib->palette, FALSE);
+ BitBlt((HDC) dc, 0, 0, dib->xsize, dib->ysize, dib->dc, 0, 0, SRCCOPY);
+}
+
+void
+ImagingDrawDIB(ImagingDIB dib, int dc, int dst[4], int src[4])
+{
+ /* Copy bitmap to printer/display */
+
+ if (GetDeviceCaps((HDC) dc, RASTERCAPS) & RC_STRETCHDIB) {
+ /* stretchdib (printers) */
+ StretchDIBits((HDC) dc, dst[0], dst[1], dst[2]-dst[0], dst[3]-dst[1],
+ src[0], src[1], src[2]-src[0], src[3]-src[1], dib->bits,
+ dib->info, DIB_RGB_COLORS, SRCCOPY);
+ } else {
+ /* stretchblt (displays) */
+ if (dib->palette != 0)
+ SelectPalette((HDC) dc, dib->palette, FALSE);
+ StretchBlt((HDC) dc, dst[0], dst[1], dst[2]-dst[0], dst[3]-dst[1],
+ dib->dc, src[0], src[1], src[2]-src[0], src[3]-src[1],
+ SRCCOPY);
+ }
+}
+
+int
+ImagingQueryPaletteDIB(ImagingDIB dib, int dc)
+{
+ /* Install bitmap palette */
+
+ int n;
+
+ if (dib->palette != 0) {
+
+ /* Realize associated palette */
+ HPALETTE now = SelectPalette((HDC) dc, dib->palette, FALSE);
+ n = RealizePalette((HDC) dc);
+
+ /* Restore palette */
+ SelectPalette((HDC) dc, now, FALSE);
+
+ } else
+ n = 0;
+
+ return n; /* number of colours that was changed */
+}
+
+void
+ImagingDeleteDIB(ImagingDIB dib)
+{
+ /* Clean up */
+
+ if (dib->palette)
+ DeleteObject(dib->palette);
+ if (dib->bitmap) {
+ SelectObject(dib->dc, dib->old_bitmap);
+ DeleteObject(dib->bitmap);
+ }
+ if (dib->dc)
+ DeleteDC(dib->dc);
+ free(dib->info);
+}
+
+#endif /* WIN32 */
diff --git a/Imaging/libImaging/Draw.c b/Imaging/libImaging/Draw.c
new file mode 100644
index 0000000..440978d
--- /dev/null
+++ b/Imaging/libImaging/Draw.c
@@ -0,0 +1,1167 @@
+/*
+ * The Python Imaging Library.
+ * $Id: Draw.c 2745 2006-06-18 17:27:41Z fredrik $
+ *
+ * a simple drawing package for the Imaging library
+ *
+ * history:
+ * 1996-04-13 fl Created.
+ * 1996-04-30 fl Added transforms and polygon support.
+ * 1996-08-12 fl Added filled polygons.
+ * 1996-11-05 fl Fixed float/int confusion in polygon filler
+ * 1997-07-04 fl Support 32-bit images (C++ would have been nice)
+ * 1998-09-09 fl Eliminated qsort casts; improved rectangle clipping
+ * 1998-09-10 fl Fixed fill rectangle to include lower edge (!)
+ * 1998-12-29 fl Added arc, chord, and pieslice primitives
+ * 1999-01-10 fl Added some level 2 ("arrow") stuff (experimental)
+ * 1999-02-06 fl Added bitmap primitive
+ * 1999-07-26 fl Eliminated a compiler warning
+ * 1999-07-31 fl Pass ink as void* instead of int
+ * 2002-12-10 fl Added experimental RGBA-on-RGB drawing
+ * 2004-09-04 fl Support simple wide lines (no joins)
+ * 2005-05-25 fl Fixed line width calculation
+ *
+ * Copyright (c) 1996-2006 by Fredrik Lundh
+ * Copyright (c) 1997-2006 by Secret Labs AB.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+/* FIXME: support fill/outline attribute for all filled shapes */
+/* FIXME: support zero-winding fill */
+/* FIXME: add drawing context, support affine transforms */
+/* FIXME: support clip window (and mask?) */
+
+#include "Imaging.h"
+
+#include <math.h>
+
+#define CEIL(v) (int) ceil(v)
+#define FLOOR(v) ((v) >= 0.0 ? (int) (v) : (int) floor(v))
+
+#define INK8(ink) (*(UINT8*)ink)
+#define INK32(ink) (*(INT32*)ink)
+
+/* like (a * b + 127) / 255), but much faster on most platforms */
+#define MULDIV255(a, b, tmp)\
+ (tmp = (a) * (b) + 128, ((((tmp) >> 8) + (tmp)) >> 8))
+
+#define BLEND(mask, in1, in2, tmp1, tmp2)\
+ (MULDIV255(in1, 255 - mask, tmp1) + MULDIV255(in2, mask, tmp2))
+
+/* -------------------------------------------------------------------- */
+/* Primitives */
+/* -------------------------------------------------------------------- */
+
+typedef struct {
+ /* edge descriptor for polygon engine */
+ int d;
+ int x0, y0;
+ int xmin, ymin, xmax, ymax;
+ float dx;
+} Edge;
+
+static inline void
+point8(Imaging im, int x, int y, int ink)
+{
+ if (x >= 0 && x < im->xsize && y >= 0 && y < im->ysize)
+ im->image8[y][x] = (UINT8) ink;
+}
+
+static inline void
+point32(Imaging im, int x, int y, int ink)
+{
+ if (x >= 0 && x < im->xsize && y >= 0 && y < im->ysize)
+ im->image32[y][x] = ink;
+}
+
+static inline void
+point32rgba(Imaging im, int x, int y, int ink)
+{
+ unsigned int tmp1, tmp2;
+
+ if (x >= 0 && x < im->xsize && y >= 0 && y < im->ysize) {
+ UINT8* out = (UINT8*) im->image[y]+x*4;
+ UINT8* in = (UINT8*) &ink;
+ out[0] = BLEND(in[3], out[0], in[0], tmp1, tmp2);
+ out[1] = BLEND(in[3], out[1], in[1], tmp1, tmp2);
+ out[2] = BLEND(in[3], out[2], in[2], tmp1, tmp2);
+ }
+}
+
+static inline void
+hline8(Imaging im, int x0, int y0, int x1, int ink)
+{
+ int tmp;
+
+ if (y0 >= 0 && y0 < im->ysize) {
+ if (x0 > x1)
+ tmp = x0, x0 = x1, x1 = tmp;
+ if (x0 < 0)
+ x0 = 0;
+ else if (x0 >= im->xsize)
+ return;
+ if (x1 < 0)
+ return;
+ else if (x1 >= im->xsize)
+ x1 = im->xsize-1;
+ if (x0 <= x1)
+ memset(im->image8[y0] + x0, (UINT8) ink, x1 - x0 + 1);
+ }
+}
+
+static inline void
+hline32(Imaging im, int x0, int y0, int x1, int ink)
+{
+ int tmp;
+ INT32* p;
+
+ if (y0 >= 0 && y0 < im->ysize) {
+ if (x0 > x1)
+ tmp = x0, x0 = x1, x1 = tmp;
+ if (x0 < 0)
+ x0 = 0;
+ else if (x0 >= im->xsize)
+ return;
+ if (x1 < 0)
+ return;
+ else if (x1 >= im->xsize)
+ x1 = im->xsize-1;
+ p = im->image32[y0];
+ while (x0 <= x1)
+ p[x0++] = ink;
+ }
+}
+
+static inline void
+hline32rgba(Imaging im, int x0, int y0, int x1, int ink)
+{
+ int tmp;
+ unsigned int tmp1, tmp2;
+
+ if (y0 >= 0 && y0 < im->ysize) {
+ if (x0 > x1)
+ tmp = x0, x0 = x1, x1 = tmp;
+ if (x0 < 0)
+ x0 = 0;
+ else if (x0 >= im->xsize)
+ return;
+ if (x1 < 0)
+ return;
+ else if (x1 >= im->xsize)
+ x1 = im->xsize-1;
+ if (x0 <= x1) {
+ UINT8* out = (UINT8*) im->image[y0]+x0*4;
+ UINT8* in = (UINT8*) &ink;
+ while (x0 <= x1) {
+ out[0] = BLEND(in[3], out[0], in[0], tmp1, tmp2);
+ out[1] = BLEND(in[3], out[1], in[1], tmp1, tmp2);
+ out[2] = BLEND(in[3], out[2], in[2], tmp1, tmp2);
+ x0++; out += 4;
+ }
+ }
+ }
+}
+
+static inline void
+line8(Imaging im, int x0, int y0, int x1, int y1, int ink)
+{
+ int i, n, e;
+ int dx, dy;
+ int xs, ys;
+
+ /* normalize coordinates */
+ dx = x1-x0;
+ if (dx < 0)
+ dx = -dx, xs = -1;
+ else
+ xs = 1;
+ dy = y1-y0;
+ if (dy < 0)
+ dy = -dy, ys = -1;
+ else
+ ys = 1;
+
+ n = (dx > dy) ? dx : dy;
+
+ if (dx == 0)
+
+ /* vertical */
+ for (i = 0; i < dy; i++) {
+ point8(im, x0, y0, ink);
+ y0 += ys;
+ }
+
+ else if (dy == 0)
+
+ /* horizontal */
+ for (i = 0; i < dx; i++) {
+ point8(im, x0, y0, ink);
+ x0 += xs;
+ }
+
+ else if (dx > dy) {
+
+ /* bresenham, horizontal slope */
+ n = dx;
+ dy += dy;
+ e = dy - dx;
+ dx += dx;
+
+ for (i = 0; i < n; i++) {
+ point8(im, x0, y0, ink);
+ if (e >= 0) {
+ y0 += ys;
+ e -= dx;
+ }
+ e += dy;
+ x0 += xs;
+ }
+
+ } else {
+
+ /* bresenham, vertical slope */
+ n = dy;
+ dx += dx;
+ e = dx - dy;
+ dy += dy;
+
+ for (i = 0; i < n; i++) {
+ point8(im, x0, y0, ink);
+ if (e >= 0) {
+ x0 += xs;
+ e -= dy;
+ }
+ e += dx;
+ y0 += ys;
+ }
+
+ }
+}
+
+static inline void
+line32(Imaging im, int x0, int y0, int x1, int y1, int ink)
+{
+ int i, n, e;
+ int dx, dy;
+ int xs, ys;
+
+ /* normalize coordinates */
+ dx = x1-x0;
+ if (dx < 0)
+ dx = -dx, xs = -1;
+ else
+ xs = 1;
+ dy = y1-y0;
+ if (dy < 0)
+ dy = -dy, ys = -1;
+ else
+ ys = 1;
+
+ n = (dx > dy) ? dx : dy;
+
+ if (dx == 0)
+
+ /* vertical */
+ for (i = 0; i < dy; i++) {
+ point32(im, x0, y0, ink);
+ y0 += ys;
+ }
+
+ else if (dy == 0)
+
+ /* horizontal */
+ for (i = 0; i < dx; i++) {
+ point32(im, x0, y0, ink);
+ x0 += xs;
+ }
+
+ else if (dx > dy) {
+
+ /* bresenham, horizontal slope */
+ n = dx;
+ dy += dy;
+ e = dy - dx;
+ dx += dx;
+
+ for (i = 0; i < n; i++) {
+ point32(im, x0, y0, ink);
+ if (e >= 0) {
+ y0 += ys;
+ e -= dx;
+ }
+ e += dy;
+ x0 += xs;
+ }
+
+ } else {
+
+ /* bresenham, vertical slope */
+ n = dy;
+ dx += dx;
+ e = dx - dy;
+ dy += dy;
+
+ for (i = 0; i < n; i++) {
+ point32(im, x0, y0, ink);
+ if (e >= 0) {
+ x0 += xs;
+ e -= dy;
+ }
+ e += dx;
+ y0 += ys;
+ }
+
+ }
+}
+
+static inline void
+line32rgba(Imaging im, int x0, int y0, int x1, int y1, int ink)
+{
+ int i, n, e;
+ int dx, dy;
+ int xs, ys;
+
+ /* normalize coordinates */
+ dx = x1-x0;
+ if (dx < 0)
+ dx = -dx, xs = -1;
+ else
+ xs = 1;
+ dy = y1-y0;
+ if (dy < 0)
+ dy = -dy, ys = -1;
+ else
+ ys = 1;
+
+ n = (dx > dy) ? dx : dy;
+
+ if (dx == 0)
+
+ /* vertical */
+ for (i = 0; i < dy; i++) {
+ point32rgba(im, x0, y0, ink);
+ y0 += ys;
+ }
+
+ else if (dy == 0)
+
+ /* horizontal */
+ for (i = 0; i < dx; i++) {
+ point32rgba(im, x0, y0, ink);
+ x0 += xs;
+ }
+
+ else if (dx > dy) {
+
+ /* bresenham, horizontal slope */
+ n = dx;
+ dy += dy;
+ e = dy - dx;
+ dx += dx;
+
+ for (i = 0; i < n; i++) {
+ point32rgba(im, x0, y0, ink);
+ if (e >= 0) {
+ y0 += ys;
+ e -= dx;
+ }
+ e += dy;
+ x0 += xs;
+ }
+
+ } else {
+
+ /* bresenham, vertical slope */
+ n = dy;
+ dx += dx;
+ e = dx - dy;
+ dy += dy;
+
+ for (i = 0; i < n; i++) {
+ point32rgba(im, x0, y0, ink);
+ if (e >= 0) {
+ x0 += xs;
+ e -= dy;
+ }
+ e += dx;
+ y0 += ys;
+ }
+
+ }
+}
+
+static int
+x_cmp(const void *x0, const void *x1)
+{
+ float diff = *((float*)x0) - *((float*)x1);
+ if (diff < 0)
+ return -1;
+ else if (diff > 0)
+ return 1;
+ else
+ return 0;
+}
+
+static inline int
+polygon8(Imaging im, int n, Edge *e, int ink, int eofill)
+{
+ int i, j;
+ float *xx;
+ int ymin, ymax;
+ float y;
+
+ if (n <= 0)
+ return 0;
+
+ /* Find upper and lower polygon boundary (within image) */
+
+ ymin = e[0].ymin;
+ ymax = e[0].ymax;
+ for (i = 1; i < n; i++) {
+ if (e[i].ymin < ymin) ymin = e[i].ymin;
+ if (e[i].ymax > ymax) ymax = e[i].ymax;
+ }
+
+ if (ymin < 0)
+ ymin = 0;
+ if (ymax >= im->ysize)
+ ymax = im->ysize-1;
+
+ /* Process polygon edges */
+
+ xx = malloc(n * sizeof(float));
+ if (!xx)
+ return -1;
+
+ for (;ymin <= ymax; ymin++) {
+ y = ymin+0.5F;
+ for (i = j = 0; i < n; i++)
+ if (y >= e[i].ymin && y <= e[i].ymax) {
+ if (e[i].d == 0)
+ hline8(im, e[i].xmin, ymin, e[i].xmax, ink);
+ else
+ xx[j++] = (y-e[i].y0) * e[i].dx + e[i].x0;
+ }
+ if (j == 2) {
+ if (xx[0] < xx[1])
+ hline8(im, CEIL(xx[0]-0.5), ymin, FLOOR(xx[1]+0.5), ink);
+ else
+ hline8(im, CEIL(xx[1]-0.5), ymin, FLOOR(xx[0]+0.5), ink);
+ } else {
+ qsort(xx, j, sizeof(float), x_cmp);
+ for (i = 0; i < j-1 ; i += 2)
+ hline8(im, CEIL(xx[i]-0.5), ymin, FLOOR(xx[i+1]+0.5), ink);
+ }
+ }
+
+ free(xx);
+
+ return 0;
+}
+
+static inline int
+polygon32(Imaging im, int n, Edge *e, int ink, int eofill)
+{
+ int i, j;
+ float *xx;
+ int ymin, ymax;
+ float y;
+
+ if (n <= 0)
+ return 0;
+
+ /* Find upper and lower polygon boundary (within image) */
+
+ ymin = e[0].ymin;
+ ymax = e[0].ymax;
+ for (i = 1; i < n; i++) {
+ if (e[i].ymin < ymin) ymin = e[i].ymin;
+ if (e[i].ymax > ymax) ymax = e[i].ymax;
+ }
+
+ if (ymin < 0)
+ ymin = 0;
+ if (ymax >= im->ysize)
+ ymax = im->ysize-1;
+
+ /* Process polygon edges */
+
+ xx = malloc(n * sizeof(float));
+ if (!xx)
+ return -1;
+
+ for (;ymin <= ymax; ymin++) {
+ y = ymin+0.5F;
+ for (i = j = 0; i < n; i++) {
+ if (y >= e[i].ymin && y <= e[i].ymax) {
+ if (e[i].d == 0)
+ hline32(im, e[i].xmin, ymin, e[i].xmax, ink);
+ else
+ xx[j++] = (y-e[i].y0) * e[i].dx + e[i].x0;
+ }
+ }
+ if (j == 2) {
+ if (xx[0] < xx[1])
+ hline32(im, CEIL(xx[0]-0.5), ymin, FLOOR(xx[1]+0.5), ink);
+ else
+ hline32(im, CEIL(xx[1]-0.5), ymin, FLOOR(xx[0]+0.5), ink);
+ } else {
+ qsort(xx, j, sizeof(float), x_cmp);
+ for (i = 0; i < j-1 ; i += 2)
+ hline32(im, CEIL(xx[i]-0.5), ymin, FLOOR(xx[i+1]+0.5), ink);
+ }
+ }
+
+ free(xx);
+
+ return 0;
+}
+
+static inline int
+polygon32rgba(Imaging im, int n, Edge *e, int ink, int eofill)
+{
+ int i, j;
+ float *xx;
+ int ymin, ymax;
+ float y;
+
+ if (n <= 0)
+ return 0;
+
+ /* Find upper and lower polygon boundary (within image) */
+
+ ymin = e[0].ymin;
+ ymax = e[0].ymax;
+ for (i = 1; i < n; i++) {
+ if (e[i].ymin < ymin) ymin = e[i].ymin;
+ if (e[i].ymax > ymax) ymax = e[i].ymax;
+ }
+
+ if (ymin < 0)
+ ymin = 0;
+ if (ymax >= im->ysize)
+ ymax = im->ysize-1;
+
+ /* Process polygon edges */
+
+ xx = malloc(n * sizeof(float));
+ if (!xx)
+ return -1;
+
+ for (;ymin <= ymax; ymin++) {
+ y = ymin+0.5F;
+ for (i = j = 0; i < n; i++) {
+ if (y >= e[i].ymin && y <= e[i].ymax) {
+ if (e[i].d == 0)
+ hline32rgba(im, e[i].xmin, ymin, e[i].xmax, ink);
+ else
+ xx[j++] = (y-e[i].y0) * e[i].dx + e[i].x0;
+ }
+ }
+ if (j == 2) {
+ if (xx[0] < xx[1])
+ hline32rgba(im, CEIL(xx[0]-0.5), ymin, FLOOR(xx[1]+0.5), ink);
+ else
+ hline32rgba(im, CEIL(xx[1]-0.5), ymin, FLOOR(xx[0]+0.5), ink);
+ } else {
+ qsort(xx, j, sizeof(float), x_cmp);
+ for (i = 0; i < j-1 ; i += 2)
+ hline32rgba(im, CEIL(xx[i]-0.5), ymin, FLOOR(xx[i+1]+0.5), ink);
+ }
+ }
+
+ free(xx);
+
+ return 0;
+}
+
+static inline void
+add_edge(Edge *e, int x0, int y0, int x1, int y1)
+{
+ /* printf("edge %d %d %d %d\n", x0, y0, x1, y1); */
+
+ if (x0 <= x1)
+ e->xmin = x0, e->xmax = x1;
+ else
+ e->xmin = x1, e->xmax = x0;
+
+ if (y0 <= y1)
+ e->ymin = y0, e->ymax = y1;
+ else
+ e->ymin = y1, e->ymax = y0;
+
+ if (y0 == y1) {
+ e->d = 0;
+ e->dx = 0.0;
+ } else {
+ e->dx = ((float)(x1-x0)) / (y1-y0);
+ if (y0 == e->ymin)
+ e->d = 1;
+ else
+ e->d = -1;
+ }
+
+ e->x0 = x0;
+ e->y0 = y0;
+}
+
+typedef struct {
+ void (*point)(Imaging im, int x, int y, int ink);
+ void (*hline)(Imaging im, int x0, int y0, int x1, int ink);
+ void (*line)(Imaging im, int x0, int y0, int x1, int y1, int ink);
+ int (*polygon)(Imaging im, int n, Edge *e, int ink, int eofill);
+} DRAW;
+
+DRAW draw8 = { point8, hline8, line8, polygon8 };
+DRAW draw32 = { point32, hline32, line32, polygon32 };
+DRAW draw32rgba = { point32rgba, hline32rgba, line32rgba, polygon32rgba };
+
+/* -------------------------------------------------------------------- */
+/* Interface */
+/* -------------------------------------------------------------------- */
+
+#define DRAWINIT()\
+ if (im->image8) {\
+ draw = &draw8;\
+ ink = INK8(ink_);\
+ } else {\
+ draw = (op) ? &draw32rgba : &draw32; \
+ ink = INK32(ink_);\
+ }
+
+int
+ImagingDrawPoint(Imaging im, int x0, int y0, const void* ink_, int op)
+{
+ DRAW* draw;
+ INT32 ink;
+
+ DRAWINIT();
+
+ draw->point(im, x0, y0, ink);
+
+ return 0;
+}
+
+int
+ImagingDrawLine(Imaging im, int x0, int y0, int x1, int y1, const void* ink_,
+ int op)
+{
+ DRAW* draw;
+ INT32 ink;
+
+ DRAWINIT();
+
+ draw->line(im, x0, y0, x1, y1, ink);
+
+ return 0;
+}
+
+int
+ImagingDrawWideLine(Imaging im, int x0, int y0, int x1, int y1,
+ const void* ink_, int width, int op)
+{
+ DRAW* draw;
+ INT32 ink;
+
+ Edge e[4];
+
+ int dx, dy;
+ double d;
+
+ DRAWINIT();
+
+ if (width <= 1) {
+ draw->line(im, x0, y0, x1, y1, ink);
+ return 0;
+ }
+
+ dx = x1-x0;
+ dy = y1-y0;
+
+ if (dx == 0 && dy == 0) {
+ draw->point(im, x0, y0, ink);
+ return 0;
+ }
+
+ d = width / sqrt(dx*dx + dy*dy) / 2.0;
+
+ dx = (int) (d * (y1-y0) + 0.5);
+ dy = (int) (d * (x1-x0) + 0.5);
+
+ add_edge(e+0, x0 - dx, y0 + dy, x1 - dx, y1 + dy);
+ add_edge(e+1, x1 - dx, y1 + dy, x1 + dx, y1 - dy);
+ add_edge(e+2, x1 + dx, y1 - dy, x0 + dx, y0 - dy);
+ add_edge(e+3, x0 + dx, y0 - dy, x0 - dx, y0 + dy);
+
+ draw->polygon(im, 4, e, ink, 0);
+
+ return 0;
+}
+
+int
+ImagingDrawRectangle(Imaging im, int x0, int y0, int x1, int y1,
+ const void* ink_, int fill, int op)
+{
+ int y;
+ int tmp;
+ DRAW* draw;
+ INT32 ink;
+
+ DRAWINIT();
+
+ if (y0 > y1)
+ tmp = y0, y0 = y1, y1 = tmp;
+
+ if (fill) {
+
+ if (y0 < 0)
+ y0 = 0;
+ else if (y0 >= im->ysize)
+ return 0;
+
+ if (y1 < 0)
+ return 0;
+ else if (y1 > im->ysize)
+ y1 = im->ysize;
+
+ for (y = y0; y <= y1; y++)
+ draw->hline(im, x0, y, x1, ink);
+
+ } else {
+
+ /* outline */
+ draw->line(im, x0, y0, x1, y0, ink);
+ draw->line(im, x1, y0, x1, y1, ink);
+ draw->line(im, x1, y1, x0, y1, ink);
+ draw->line(im, x0, y1, x0, y0, ink);
+
+ }
+
+ return 0;
+}
+
+int
+ImagingDrawPolygon(Imaging im, int count, int* xy, const void* ink_,
+ int fill, int op)
+{
+ int i, n;
+ DRAW* draw;
+ INT32 ink;
+
+ if (count <= 0)
+ return 0;
+
+ DRAWINIT();
+
+ if (fill) {
+
+ /* Build edge list */
+ Edge* e = malloc(count * sizeof(Edge));
+ if (!e) {
+ ImagingError_MemoryError();
+ return -1;
+ }
+ for (i = n = 0; i < count-1; i++)
+ add_edge(&e[n++], xy[i+i], xy[i+i+1], xy[i+i+2], xy[i+i+3]);
+ if (xy[i+i] != xy[0] || xy[i+i+1] != xy[1])
+ add_edge(&e[n++], xy[i+i], xy[i+i+1], xy[0], xy[1]);
+ draw->polygon(im, n, e, ink, 0);
+ free(e);
+
+ } else {
+
+ /* Outline */
+ for (i = 0; i < count-1; i++)
+ draw->line(im, xy[i+i], xy[i+i+1], xy[i+i+2], xy[i+i+3], ink);
+ draw->line(im, xy[i+i], xy[i+i+1], xy[0], xy[1], ink);
+
+ }
+
+ return 0;
+}
+
+int
+ImagingDrawBitmap(Imaging im, int x0, int y0, Imaging bitmap, const void* ink,
+ int op)
+{
+ return ImagingFill2(
+ im, ink, bitmap,
+ x0, y0, x0 + bitmap->xsize, y0 + bitmap->ysize
+ );
+}
+
+/* -------------------------------------------------------------------- */
+/* standard shapes */
+
+#define ARC 0
+#define CHORD 1
+#define PIESLICE 2
+
+static int
+ellipse(Imaging im, int x0, int y0, int x1, int y1,
+ int start, int end, const void* ink_, int fill,
+ int mode, int op)
+{
+ int i, n;
+ int cx, cy;
+ int w, h;
+ int x = 0, y = 0;
+ int lx = 0, ly = 0;
+ int sx = 0, sy = 0;
+ DRAW* draw;
+ INT32 ink;
+
+ w = x1 - x0;
+ h = y1 - y0;
+ if (w < 0 || h < 0)
+ return 0;
+
+ DRAWINIT();
+
+ cx = (x0 + x1) / 2;
+ cy = (y0 + y1) / 2;
+
+ while (end < start)
+ end += 360;
+
+ if (mode != ARC && fill) {
+
+ /* Build edge list */
+ Edge* e = malloc((end - start + 3) * sizeof(Edge));
+ if (!e) {
+ ImagingError_MemoryError();
+ return -1;
+ }
+
+ n = 0;
+
+ for (i = start; i <= end; i++) {
+ x = FLOOR((cos(i*M_PI/180) * w/2) + cx + 0.5);
+ y = FLOOR((sin(i*M_PI/180) * h/2) + cy + 0.5);
+ if (i != start)
+ add_edge(&e[n++], lx, ly, x, y);
+ else
+ sx = x, sy = y;
+ lx = x, ly = y;
+ }
+
+ if (n > 0) {
+ /* close and draw polygon */
+ if (mode == PIESLICE) {
+ if (x != cx || y != cy) {
+ add_edge(&e[n++], x, y, cx, cy);
+ add_edge(&e[n++], cx, cy, sx, sy);
+ }
+ } else {
+ if (x != sx || y != sy)
+ add_edge(&e[n++], x, y, sx, sy);
+ }
+ draw->polygon(im, n, e, ink, 0);
+ }
+
+ free(e);
+
+ } else {
+
+ for (i = start; i <= end; i++) {
+ x = FLOOR((cos(i*M_PI/180) * w/2) + cx + 0.5);
+ y = FLOOR((sin(i*M_PI/180) * h/2) + cy + 0.5);
+ if (i != start)
+ draw->line(im, lx, ly, x, y, ink);
+ else
+ sx = x, sy = y;
+ lx = x, ly = y;
+ }
+
+ if (i != start) {
+ if (mode == PIESLICE) {
+ if (x != cx || y != cy) {
+ draw->line(im, x, y, cx, cy, ink);
+ draw->line(im, cx, cy, sx, sy, ink);
+ }
+ } else if (mode == CHORD) {
+ if (x != sx || y != sy)
+ draw->line(im, x, y, sx, sy, ink);
+ }
+ }
+ }
+
+ return 0;
+}
+
+int
+ImagingDrawArc(Imaging im, int x0, int y0, int x1, int y1,
+ int start, int end, const void* ink, int op)
+{
+ return ellipse(im, x0, y0, x1, y1, start, end, ink, 0, ARC, op);
+}
+
+int
+ImagingDrawChord(Imaging im, int x0, int y0, int x1, int y1,
+ int start, int end, const void* ink, int fill, int op)
+{
+ return ellipse(im, x0, y0, x1, y1, start, end, ink, fill, CHORD, op);
+}
+
+int
+ImagingDrawEllipse(Imaging im, int x0, int y0, int x1, int y1,
+ const void* ink, int fill, int op)
+{
+ return ellipse(im, x0, y0, x1, y1, 0, 360, ink, fill, CHORD, op);
+}
+
+int
+ImagingDrawPieslice(Imaging im, int x0, int y0, int x1, int y1,
+ int start, int end, const void* ink, int fill, int op)
+{
+ return ellipse(im, x0, y0, x1, y1, start, end, ink, fill, PIESLICE, op);
+}
+
+/* -------------------------------------------------------------------- */
+
+/* experimental level 2 ("arrow") graphics stuff. this implements
+ portions of the arrow api on top of the Edge structure. the
+ semantics are ok, except that "curve" flattens the bezier curves by
+ itself */
+
+#if 1 /* ARROW_GRAPHICS */
+
+struct ImagingOutlineInstance {
+
+ float x0, y0;
+
+ float x, y;
+
+ int count;
+ Edge *edges;
+
+ int size;
+
+};
+
+
+ImagingOutline
+ImagingOutlineNew(void)
+{
+ ImagingOutline outline;
+
+ outline = calloc(1, sizeof(struct ImagingOutlineInstance));
+ if (!outline)
+ return (ImagingOutline) ImagingError_MemoryError();
+
+ outline->edges = NULL;
+ outline->count = outline->size = 0;
+
+ ImagingOutlineMove(outline, 0, 0);
+
+ return outline;
+}
+
+void
+ImagingOutlineDelete(ImagingOutline outline)
+{
+ if (!outline)
+ return;
+
+ if (outline->edges)
+ free(outline->edges);
+
+ free(outline);
+}
+
+
+static Edge*
+allocate(ImagingOutline outline, int extra)
+{
+ Edge* e;
+
+ if (outline->count + extra > outline->size) {
+ /* expand outline buffer */
+ outline->size += extra + 25;
+ if (!outline->edges)
+ e = malloc(outline->size * sizeof(Edge));
+ else
+ e = realloc(outline->edges, outline->size * sizeof(Edge));
+ if (!e)
+ return NULL;
+ outline->edges = e;
+ }
+
+ e = outline->edges + outline->count;
+
+ outline->count += extra;
+
+ return e;
+}
+
+int
+ImagingOutlineMove(ImagingOutline outline, float x0, float y0)
+{
+ outline->x = outline->x0 = x0;
+ outline->y = outline->y0 = y0;
+
+ return 0;
+}
+
+int
+ImagingOutlineLine(ImagingOutline outline, float x1, float y1)
+{
+ Edge* e;
+
+ e = allocate(outline, 1);
+ if (!e)
+ return -1; /* out of memory */
+
+ add_edge(e, (int) outline->x, (int) outline->y, (int) x1, (int) y1);
+
+ outline->x = x1;
+ outline->y = y1;
+
+ return 0;
+}
+
+int
+ImagingOutlineCurve(ImagingOutline outline, float x1, float y1,
+ float x2, float y2, float x3, float y3)
+{
+ Edge* e;
+ int i;
+ float xo, yo;
+
+#define STEPS 32
+
+ e = allocate(outline, STEPS);
+ if (!e)
+ return -1; /* out of memory */
+
+ xo = outline->x;
+ yo = outline->y;
+
+ /* flatten the bezier segment */
+
+ for (i = 1; i <= STEPS; i++) {
+
+ float t = ((float) i) / STEPS;
+ float t2 = t*t;
+ float t3 = t2*t;
+
+ float u = 1.0F - t;
+ float u2 = u*u;
+ float u3 = u2*u;
+
+ float x = outline->x*u3 + 3*(x1*t*u2 + x2*t2*u) + x3*t3 + 0.5;
+ float y = outline->y*u3 + 3*(y1*t*u2 + y2*t2*u) + y3*t3 + 0.5;
+
+ add_edge(e++, xo, yo, (int) x, (int) y);
+
+ xo = x, yo = y;
+
+ }
+
+ outline->x = xo;
+ outline->y = yo;
+
+ return 0;
+}
+
+int
+ImagingOutlineCurve2(ImagingOutline outline, float cx, float cy,
+ float x3, float y3)
+{
+ /* add bezier curve based on three control points (as
+ in the Flash file format) */
+
+ return ImagingOutlineCurve(
+ outline,
+ (outline->x + cx + cx)/3, (outline->y + cy + cy)/3,
+ (cx + cx + x3)/3, (cy + cy + y3)/3,
+ x3, y3);
+}
+
+int
+ImagingOutlineClose(ImagingOutline outline)
+{
+ if (outline->x == outline->x0 && outline->y == outline->y0)
+ return 0;
+ return ImagingOutlineLine(outline, outline->x0, outline->y0);
+}
+
+int
+ImagingOutlineTransform(ImagingOutline outline, double a[6])
+{
+ Edge *eIn;
+ Edge *eOut;
+ int i, n;
+ int x0, y0, x1, y1;
+ int X0, Y0, X1, Y1;
+
+ double a0 = a[0]; double a1 = a[1]; double a2 = a[2];
+ double a3 = a[3]; double a4 = a[4]; double a5 = a[5];
+
+ eIn = outline->edges;
+ n = outline->count;
+
+ /* FIXME: ugly! */
+ outline->edges = NULL;
+ outline->count = outline->size = 0;
+
+ eOut = allocate(outline, n);
+ if (!eOut) {
+ outline->edges = eIn;
+ outline->count = outline->size = n;
+ ImagingError_MemoryError();
+ return -1;
+ }
+
+ for (i = 0; i < n; i++) {
+
+ x0 = eIn->x0;
+ y0 = eIn->y0;
+
+ /* FIXME: ouch! */
+ if (eIn->x0 == eIn->xmin)
+ x1 = eIn->xmax;
+ else
+ x1 = eIn->xmin;
+ if (eIn->y0 == eIn->ymin)
+ y1 = eIn->ymax;
+ else
+ y1 = eIn->ymin;
+
+ /* full moon tonight! if this doesn't work, you may need to
+ upgrade your compiler (make sure you have the right service
+ pack) */
+
+ X0 = (int) (a0*x0 + a1*y0 + a2);
+ Y0 = (int) (a3*x0 + a4*y0 + a5);
+ X1 = (int) (a0*x1 + a1*y1 + a2);
+ Y1 = (int) (a3*x1 + a4*y1 + a5);
+
+ add_edge(eOut, X0, Y0, X1, Y1);
+
+ eIn++;
+ eOut++;
+
+ }
+
+ free(eIn);
+
+ return 0;
+}
+
+int
+ImagingDrawOutline(Imaging im, ImagingOutline outline, const void* ink_,
+ int fill, int op)
+{
+ DRAW* draw;
+ INT32 ink;
+
+ DRAWINIT();
+
+ draw->polygon(im, outline->count, outline->edges, ink, 0);
+
+ return 0;
+}
+
+#endif
diff --git a/Imaging/libImaging/Effects.c b/Imaging/libImaging/Effects.c
new file mode 100644
index 0000000..2ec08c7
--- /dev/null
+++ b/Imaging/libImaging/Effects.c
@@ -0,0 +1,370 @@
+/*
+ * The Python Imaging Library
+ * $Id: Effects.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * various special effects and image generators
+ *
+ * history:
+ * 1997-05-21 fl Just for fun
+ * 1997-06-05 fl Added mandelbrot generator
+ * 2003-05-24 fl Added perlin_turbulence generator (in progress)
+ *
+ * Copyright (c) 1997-2003 by Fredrik Lundh.
+ * Copyright (c) 1997 by Secret Labs AB.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+#include <math.h>
+
+Imaging
+ImagingEffectMandelbrot(int xsize, int ysize, double extent[4], int quality)
+{
+ /* Generate a Mandelbrot set covering the given extent */
+
+ Imaging im;
+ int x, y, k;
+ double width, height;
+ double x1, y1, xi2, yi2, cr, ci, radius;
+ double dr, di;
+
+ /* Check arguments */
+ width = extent[2] - extent[0];
+ height = extent[3] - extent[1];
+ if (width < 0.0 || height < 0.0 || quality < 2)
+ return (Imaging) ImagingError_ValueError(NULL);
+
+ im = ImagingNew("L", xsize, ysize);
+ if (!im)
+ return NULL;
+
+ dr = width/(xsize-1);
+ di = height/(ysize-1);
+
+ radius = 100.0;
+
+ for (y = 0; y < ysize; y++) {
+ UINT8* buf = im->image8[y];
+ for (x = 0; x < xsize; x++) {
+ x1 = y1 = xi2 = yi2 = 0.0;
+ cr = x*dr + extent[0];
+ ci = y*di + extent[1];
+ for (k = 1;; k++) {
+ y1 = 2*x1*y1 + ci;
+ x1 = xi2 - yi2 + cr;
+ xi2 = x1*x1;
+ yi2 = y1*y1;
+ if ((xi2 + yi2) > radius) {
+ buf[x] = k*255/quality;
+ break;
+ }
+ if (k > quality) {
+ buf[x] = 0;
+ break;
+ }
+ }
+ }
+ }
+ return im;
+}
+
+Imaging
+ImagingEffectNoise(int xsize, int ysize, float sigma)
+{
+ /* Generate gaussian noise centered around 128 */
+
+ Imaging imOut;
+ int x, y;
+ int nextok;
+ double this, next;
+
+ imOut = ImagingNew("L", xsize, ysize);
+ if (!imOut)
+ return NULL;
+
+ next = 0.0;
+ nextok = 0;
+
+ for (y = 0; y < imOut->ysize; y++) {
+ UINT8* out = imOut->image8[y];
+ for (x = 0; x < imOut->xsize; x++) {
+ if (nextok) {
+ this = next;
+ nextok = 0;
+ } else {
+ /* after numerical recepies */
+ double v1, v2, radius, factor;
+ do {
+ v1 = rand()*(2.0/32767.0) - 1.0;
+ v2 = rand()*(2.0/32767.0) - 1.0;
+ radius= v1*v1 + v2*v2;
+ } while (radius >= 1.0);
+ factor = sqrt(-2.0*log(radius)/radius);
+ this = factor * v1;
+ next = factor * v2;
+ }
+ out[x] = (unsigned char) (128 + sigma * this);
+ }
+ }
+
+ return imOut;
+}
+
+Imaging
+ImagingEffectPerlinTurbulence(int xsize, int ysize)
+{
+ /* Perlin turbulence (In progress) */
+
+ return NULL;
+}
+
+Imaging
+ImagingEffectSpread(Imaging imIn, int distance)
+{
+ /* Randomly spread pixels in an image */
+
+ Imaging imOut;
+ int x, y;
+
+ imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize);
+
+ if (!imOut)
+ return NULL;
+
+#define SPREAD(type, image)\
+ for (y = 0; y < imIn->ysize; y++)\
+ for (x = 0; x < imIn->xsize; x++) {\
+ int xx = x + (rand() % distance) - distance/2;\
+ int yy = y + (rand() % distance) - distance/2;\
+ if (xx >= 0 && xx < imIn->xsize && yy >= 0 && yy < imIn->ysize) {\
+ imOut->image[yy][xx] = imIn->image[y][x];\
+ imOut->image[y][x] = imIn->image[yy][xx];\
+ } else\
+ imOut->image[y][x] = imIn->image[y][x];\
+ }
+
+ if (imIn->image8) {
+ SPREAD(UINT8, image8);
+ } else {
+ SPREAD(INT32, image32);
+ }
+
+ ImagingCopyInfo(imOut, imIn);
+
+ return imOut;
+}
+
+/* -------------------------------------------------------------------- */
+/* Taken from the "C" code in the W3C SVG specification. Translated
+ to C89 by Fredrik Lundh */
+
+/* Produces results in the range [1, 2**31 - 2].
+Algorithm is: r = (a * r) mod m
+where a = 16807 and m = 2**31 - 1 = 2147483647
+See [Park & Miller], CACM vol. 31 no. 10 p. 1195, Oct. 1988
+To test: the algorithm should produce the result 1043618065
+as the 10,000th generated number if the original seed is 1.
+*/
+#define RAND_m 2147483647 /* 2**31 - 1 */
+#define RAND_a 16807 /* 7**5; primitive root of m */
+#define RAND_q 127773 /* m / a */
+#define RAND_r 2836 /* m % a */
+
+static long
+perlin_setup_seed(long lSeed)
+{
+ if (lSeed <= 0) lSeed = -(lSeed % (RAND_m - 1)) + 1;
+ if (lSeed > RAND_m - 1) lSeed = RAND_m - 1;
+ return lSeed;
+}
+
+static long
+perlin_random(long lSeed)
+{
+ long result;
+ result = RAND_a * (lSeed % RAND_q) - RAND_r * (lSeed / RAND_q);
+ if (result <= 0) result += RAND_m;
+ return result;
+}
+
+#define BSize 0x100
+#define BM 0xff
+#define PerlinN 0x1000
+#define NP 12 /* 2^PerlinN */
+#define NM 0xfff
+static int perlin_uLatticeSelector[BSize + BSize + 2];
+static double perlin_fGradient[4][BSize + BSize + 2][2];
+typedef struct
+{
+ int nWidth; /* How much to subtract to wrap for stitching. */
+ int nHeight;
+ int nWrapX; /* Minimum value to wrap. */
+ int nWrapY;
+} StitchInfo;
+
+static void
+perlin_init(long lSeed)
+{
+ double s;
+ int i, j, k;
+ lSeed = perlin_setup_seed(lSeed);
+ for(k = 0; k < 4; k++)
+ {
+ for(i = 0; i < BSize; i++)
+ {
+ perlin_uLatticeSelector[i] = i;
+ for (j = 0; j < 2; j++)
+ perlin_fGradient[k][i][j] = (double)(((lSeed = perlin_random(lSeed)) % (BSize + BSize)) - BSize) / BSize;
+ s = (double) (sqrt(perlin_fGradient[k][i][0] * perlin_fGradient[k][i][0] + perlin_fGradient[k][i][1] * perlin_fGradient[k][i][1]));
+ perlin_fGradient[k][i][0] /= s;
+ perlin_fGradient[k][i][1] /= s;
+ }
+ }
+ while(--i)
+ {
+ k = perlin_uLatticeSelector[i];
+ perlin_uLatticeSelector[i] = perlin_uLatticeSelector[j = (lSeed = perlin_random(lSeed)) % BSize];
+ perlin_uLatticeSelector[j] = k;
+ }
+ for(i = 0; i < BSize + 2; i++)
+ {
+ perlin_uLatticeSelector[BSize + i] = perlin_uLatticeSelector[i];
+ for(k = 0; k < 4; k++)
+ for(j = 0; j < 2; j++)
+ perlin_fGradient[k][BSize + i][j] = perlin_fGradient[k][i][j];
+ }
+}
+
+#define s_curve(t) ( t * t * (3. - 2. * t) )
+#define lerp(t, a, b) ( a + t * (b - a) )
+static double
+perlin_noise2(int nColorChannel, double vec[2], StitchInfo *pStitchInfo)
+{
+ int bx0, bx1, by0, by1, b00, b10, b01, b11;
+ double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
+ register int i, j;
+
+ t = vec[0] + (double) PerlinN;
+ bx0 = (int)t;
+ bx1 = bx0+1;
+ rx0 = t - (int)t;
+ rx1 = rx0 - 1.0f;
+ t = vec[1] + (double) PerlinN;
+ by0 = (int)t;
+ by1 = by0+1;
+ ry0 = t - (int)t;
+ ry1 = ry0 - 1.0f;
+
+ /* If stitching, adjust lattice points accordingly. */
+ if(pStitchInfo != NULL)
+ {
+ if(bx0 >= pStitchInfo->nWrapX)
+ bx0 -= pStitchInfo->nWidth;
+ if(bx1 >= pStitchInfo->nWrapX)
+ bx1 -= pStitchInfo->nWidth;
+ if(by0 >= pStitchInfo->nWrapY)
+ by0 -= pStitchInfo->nHeight;
+ if(by1 >= pStitchInfo->nWrapY)
+ by1 -= pStitchInfo->nHeight;
+ }
+
+ bx0 &= BM;
+ bx1 &= BM;
+ by0 &= BM;
+ by1 &= BM;
+
+ i = perlin_uLatticeSelector[bx0];
+ j = perlin_uLatticeSelector[bx1];
+ b00 = perlin_uLatticeSelector[i + by0];
+ b10 = perlin_uLatticeSelector[j + by0];
+ b01 = perlin_uLatticeSelector[i + by1];
+ b11 = perlin_uLatticeSelector[j + by1];
+ sx = (double) (s_curve(rx0));
+ sy = (double) (s_curve(ry0));
+ q = perlin_fGradient[nColorChannel][b00]; u = rx0 * q[0] + ry0 * q[1];
+ q = perlin_fGradient[nColorChannel][b10]; v = rx1 * q[0] + ry0 * q[1];
+ a = lerp(sx, u, v);
+ q = perlin_fGradient[nColorChannel][b01]; u = rx0 * q[0] + ry1 * q[1];
+ q = perlin_fGradient[nColorChannel][b11]; v = rx1 * q[0] + ry1 * q[1];
+ b = lerp(sx, u, v);
+ return lerp(sy, a, b);
+}
+
+double
+perlin_turbulence(
+ int nColorChannel, double *point, double fBaseFreqX, double fBaseFreqY,
+ int nNumOctaves, int bFractalSum, int bDoStitching,
+ double fTileX, double fTileY, double fTileWidth, double fTileHeight)
+{
+ StitchInfo stitch;
+ StitchInfo *pStitchInfo = NULL; /* Not stitching when NULL. */
+
+ double fSum = 0.0f;
+ double vec[2];
+ double ratio = 1;
+
+ int nOctave;
+
+ vec[0] = point[0] * fBaseFreqX;
+ vec[1] = point[1] * fBaseFreqY;
+
+ /* Adjust the base frequencies if necessary for stitching. */
+ if(bDoStitching)
+ {
+ /* When stitching tiled turbulence, the frequencies must be adjusted */
+ /* so that the tile borders will be continuous. */
+ if(fBaseFreqX != 0.0)
+ {
+ double fLoFreq = (double) (floor(fTileWidth * fBaseFreqX)) / fTileWidth;
+ double fHiFreq = (double) (ceil(fTileWidth * fBaseFreqX)) / fTileWidth;
+ if(fBaseFreqX / fLoFreq < fHiFreq / fBaseFreqX)
+ fBaseFreqX = fLoFreq;
+ else
+ fBaseFreqX = fHiFreq;
+ }
+
+ if(fBaseFreqY != 0.0)
+ {
+ double fLoFreq = (double) (floor(fTileHeight * fBaseFreqY)) / fTileHeight;
+ double fHiFreq = (double) (ceil(fTileHeight * fBaseFreqY)) / fTileHeight;
+ if(fBaseFreqY / fLoFreq < fHiFreq / fBaseFreqY)
+ fBaseFreqY = fLoFreq;
+ else
+ fBaseFreqY = fHiFreq;
+ }
+
+ /* Set up initial stitch values. */
+ pStitchInfo = &stitch;
+ stitch.nWidth = (int) (fTileWidth * fBaseFreqX + 0.5f);
+ stitch.nWrapX = (int) (fTileX * fBaseFreqX + PerlinN + stitch.nWidth);
+ stitch.nHeight = (int) (fTileHeight * fBaseFreqY + 0.5f);
+ stitch.nWrapY = (int) (fTileY * fBaseFreqY + PerlinN + stitch.nHeight);
+ }
+
+ for(nOctave = 0; nOctave < nNumOctaves; nOctave++)
+ {
+ if(bFractalSum)
+ fSum += (double) (perlin_noise2(nColorChannel, vec, pStitchInfo) / ratio);
+ else
+ fSum += (double) (fabs(perlin_noise2(nColorChannel, vec, pStitchInfo)) / ratio);
+
+ vec[0] *= 2;
+ vec[1] *= 2;
+ ratio *= 2;
+
+ if(pStitchInfo != NULL)
+ {
+ /* Update stitch values. Subtracting PerlinN before the multiplication and */
+ /* adding it afterward simplifies to subtracting it once. */
+ stitch.nWidth *= 2;
+ stitch.nWrapX = 2 * stitch.nWrapX - PerlinN;
+ stitch.nHeight *= 2;
+ stitch.nWrapY = 2 * stitch.nWrapY - PerlinN;
+ }
+ }
+ return fSum;
+}
+
diff --git a/Imaging/libImaging/EpsEncode.c b/Imaging/libImaging/EpsEncode.c
new file mode 100644
index 0000000..0e62c2d
--- /dev/null
+++ b/Imaging/libImaging/EpsEncode.c
@@ -0,0 +1,80 @@
+/*
+ * The Python Imaging Library.
+ * $Id: EpsEncode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * encoder for EPS hex data
+ *
+ * history:
+ * 96-04-19 fl created
+ * 96-06-27 fl don't drop last block of encoded data
+ *
+ * notes:
+ * FIXME: rename to HexEncode.c ??
+ *
+ * Copyright (c) Fredrik Lundh 1996.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+int
+ImagingEpsEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ enum { HEXBYTE=1, NEWLINE };
+ const char *hex = "0123456789abcdef";
+
+ UINT8* ptr = buf;
+ UINT8* in, i;
+
+ if (!state->state) {
+ state->state = HEXBYTE;
+ state->xsize *= im->pixelsize; /* Hack! */
+ }
+
+ in = (UINT8*) im->image[state->y];
+
+ for (;;) {
+
+ if (state->state == NEWLINE) {
+ if (bytes < 1)
+ break;
+ *ptr++ = '\n';
+ bytes--;
+ state->state = HEXBYTE;
+ }
+
+ if (bytes < 2)
+ break;
+
+ i = in[state->x++];
+ *ptr++ = hex[(i>>4)&15];
+ *ptr++ = hex[i&15];
+ bytes -= 2;
+
+ /* Skip junk bytes */
+ if (im->bands == 3 && (state->x & 3) == 3)
+ state->x++;
+
+ if (++state->count >= 79/2) {
+ state->state = NEWLINE;
+ state->count = 0;
+ }
+
+ if (state->x >= state->xsize) {
+ state->x = 0;
+ if (++state->y >= state->ysize) {
+ state->errcode = IMAGING_CODEC_END;
+ break;
+ }
+ in = (UINT8*) im->image[state->y];
+ }
+
+ }
+
+ return ptr - buf;
+
+}
diff --git a/Imaging/libImaging/Except.c b/Imaging/libImaging/Except.c
new file mode 100644
index 0000000..cab0699
--- /dev/null
+++ b/Imaging/libImaging/Except.c
@@ -0,0 +1,78 @@
+/*
+ * The Python Imaging Library
+ * $Id: Except.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * default exception handling
+ *
+ * This module is usually overridden by application code (e.g.
+ * _imaging.c for PIL's standard Python bindings). If you get
+ * linking errors, remove this file from your project/library.
+ *
+ * history:
+ * 1995-06-15 fl Created
+ * 1998-12-29 fl Minor tweaks
+ * 2003-09-13 fl Added ImagingEnter/LeaveSection()
+ *
+ * Copyright (c) 1997-2003 by Secret Labs AB.
+ * Copyright (c) 1995-2003 by Fredrik Lundh.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+/* exception state */
+
+void *
+ImagingError_IOError(void)
+{
+ fprintf(stderr, "*** exception: file access error\n");
+ return NULL;
+}
+
+void *
+ImagingError_MemoryError(void)
+{
+ fprintf(stderr, "*** exception: out of memory\n");
+ return NULL;
+}
+
+void *
+ImagingError_ModeError(void)
+{
+ return ImagingError_ValueError("bad image mode");
+ return NULL;
+}
+
+void *
+ImagingError_Mismatch(void)
+{
+ return ImagingError_ValueError("images don't match");
+ return NULL;
+}
+
+void *
+ImagingError_ValueError(const char *message)
+{
+ if (!message)
+ message = "exception: bad argument to function";
+ fprintf(stderr, "*** %s\n", message);
+ return NULL;
+}
+
+
+/* thread state */
+
+void
+ImagingSectionEnter(ImagingSectionCookie* cookie)
+{
+ /* pass */
+}
+
+void
+ImagingSectionLeave(ImagingSectionCookie* cookie)
+{
+ /* pass */
+}
diff --git a/Imaging/libImaging/File.c b/Imaging/libImaging/File.c
new file mode 100644
index 0000000..00f52d3
--- /dev/null
+++ b/Imaging/libImaging/File.c
@@ -0,0 +1,198 @@
+/*
+ * The Python Imaging Library
+ * $Id: File.c 2507 2005-09-10 14:53:47Z fredrik $
+ *
+ * built-in image file handling
+ *
+ * history:
+ * 1995-11-26 fl Created, supports PGM/PPM
+ * 1996-08-07 fl Write "1" images as PGM
+ * 1999-02-21 fl Don't write non-standard modes
+ *
+ * Copyright (c) 1997-99 by Secret Labs AB.
+ * Copyright (c) 1995-96 by Fredrik Lundh.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+#include <ctype.h>
+
+Imaging
+ImagingOpenPPM(const char* infile)
+{
+ FILE* fp;
+ int i, c, v;
+ char* mode;
+ int x, y, max;
+ Imaging im;
+
+ if (!infile)
+ return ImagingError_ValueError(NULL);
+
+ fp = fopen(infile, "rb");
+ if (!fp)
+ return ImagingError_IOError();
+
+ /* PPM magic */
+ if (fgetc(fp) != 'P')
+ goto syntax;
+ switch (fgetc(fp)) {
+ case '4': /* FIXME: 1-bit images are not yet supported */
+ goto syntax;
+ case '5':
+ mode = "L";
+ break;
+ case '6':
+ mode = "RGB";
+ break;
+ default:
+ goto syntax;
+ }
+
+ i = 0;
+ c = fgetc(fp);
+
+ x = y = max = 0;
+
+ while (i < 3) {
+
+ /* Ignore optional comment fields */
+ while (c == '\n') {
+ c = fgetc(fp);
+ if (c == '#') {
+ do {
+ c = fgetc(fp);
+ if (c == EOF)
+ goto syntax;
+ } while (c != '\n');
+ c = fgetc(fp);
+ }
+ }
+
+ /* Skip forward to next value */
+ while (isspace(c))
+ c = fgetc(fp);
+
+ /* And parse it */
+ v = 0;
+ while (isdigit(c)) {
+ v = v * 10 + (c - '0');
+ c = fgetc(fp);
+ }
+
+ if (c == EOF)
+ goto syntax;
+
+ switch (i++) {
+ case 0:
+ x = v;
+ break;
+ case 1:
+ y = v;
+ break;
+ case 2:
+ max = v;
+ break;
+ }
+ }
+
+ im = ImagingNew(mode, x, y);
+ if (!im)
+ return NULL;
+
+ /* if (max != 255) ... FIXME: does anyone ever use this feature? */
+
+ if (strcmp(im->mode, "L") == 0) {
+
+ /* PPM "L" */
+ for (y = 0; y < im->ysize; y++)
+ fread(im->image[y], 1, im->xsize, fp);
+
+ } else {
+
+ /* PPM "RGB" or PyPPM mode */
+ for (y = 0; y < im->ysize; y++)
+ for (x = i = 0; x < im->xsize; x++, i += im->pixelsize)
+ fread(im->image[y]+i, 1, im->bands, fp);
+
+ }
+
+ fclose(fp);
+
+ return im;
+
+syntax:
+ fclose(fp);
+ return ImagingError_IOError();
+}
+
+
+int
+ImagingSaveRaw(Imaging im, FILE* fp)
+{
+ int x, y, i;
+
+ if (strcmp(im->mode, "1") == 0 || strcmp(im->mode, "L") == 0) {
+
+ /* @PIL227: FIXME: for mode "1", map != 0 to 255 */
+
+ /* PGM "L" */
+ for (y = 0; y < im->ysize; y++)
+ fwrite(im->image[y], 1, im->xsize, fp);
+
+ } else {
+
+ /* PPM "RGB" or other internal format */
+ for (y = 0; y < im->ysize; y++)
+ for (x = i = 0; x < im->xsize; x++, i += im->pixelsize)
+ fwrite(im->image[y]+i, 1, im->bands, fp);
+
+ }
+
+ return 1;
+}
+
+
+int
+ImagingSavePPM(Imaging im, const char* outfile)
+{
+ FILE* fp;
+
+ if (!im) {
+ ImagingError_ValueError(NULL);
+ return 0;
+ }
+
+ fp = fopen(outfile, "wb");
+ if (!fp) {
+ ImagingError_IOError();
+ return 0;
+ }
+
+ if (strcmp(im->mode, "1") == 0 || strcmp(im->mode, "L") == 0) {
+
+ /* Write "PGM" */
+ fprintf(fp, "P5\n%d %d\n255\n", im->xsize, im->ysize);
+
+ } else if (strcmp(im->mode, "RGB") == 0) {
+
+ /* Write "PPM" */
+ fprintf(fp, "P6\n%d %d\n255\n", im->xsize, im->ysize);
+
+ } else {
+
+ ImagingError_ModeError();
+ return 0;
+
+ }
+
+ ImagingSaveRaw(im, fp);
+
+ fclose(fp);
+
+ return 1;
+}
+
diff --git a/Imaging/libImaging/Fill.c b/Imaging/libImaging/Fill.c
new file mode 100644
index 0000000..f900a99
--- /dev/null
+++ b/Imaging/libImaging/Fill.c
@@ -0,0 +1,89 @@
+/*
+ * The Python Imaging Library
+ * $Id: Fill.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * fill image with constant pixel value
+ *
+ * history:
+ * 95-11-26 fl moved from Imaging.c
+ * 96-05-17 fl added radial fill, renamed wedge to linear
+ * 98-06-23 fl changed ImageFill signature
+ *
+ * Copyright (c) Secret Labs AB 1997-98. All rights reserved.
+ * Copyright (c) Fredrik Lundh 1995-96.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+#include "math.h"
+
+
+Imaging
+ImagingFill(Imaging im, const void* colour)
+{
+ INT32 c;
+ int x, y;
+
+ c = 0L;
+ memcpy(&c, colour, im->pixelsize);
+
+ if (im->image32 && c != 0L) {
+ for (y = 0; y < im->ysize; y++)
+ for (x = 0; x < im->xsize; x++)
+ im->image32[y][x] = c;
+ } else {
+ unsigned char cc = (unsigned char) *(UINT8*) colour;
+ for (y = 0; y < im->ysize; y++)
+ memset(im->image[y], cc, im->linesize);
+ }
+
+ return im;
+}
+
+Imaging
+ImagingFillLinearGradient(const char *mode)
+{
+ Imaging im;
+ int y;
+
+ if (strlen(mode) != 1)
+ return (Imaging) ImagingError_ModeError();
+
+ im = ImagingNew(mode, 256, 256);
+ if (!im)
+ return NULL;
+
+ for (y = 0; y < 256; y++)
+ memset(im->image8[y], (unsigned char) y, 256);
+
+ return im;
+}
+
+Imaging
+ImagingFillRadialGradient(const char *mode)
+{
+ Imaging im;
+ int x, y;
+ int d;
+
+ if (strlen(mode) != 1)
+ return (Imaging) ImagingError_ModeError();
+
+ im = ImagingNew(mode, 256, 256);
+ if (!im)
+ return NULL;
+
+ for (y = 0; y < 256; y++)
+ for (x = 0; x < 256; x++) {
+ d = (int) sqrt((double) ((x-128)*(x-128) + (y-128)*(y-128)) * 2.0);
+ if (d >= 255)
+ im->image8[y][x] = 255;
+ else
+ im->image8[y][x] = d;
+ }
+
+ return im;
+}
diff --git a/Imaging/libImaging/Filter.c b/Imaging/libImaging/Filter.c
new file mode 100644
index 0000000..b73ca9f
--- /dev/null
+++ b/Imaging/libImaging/Filter.c
@@ -0,0 +1,176 @@
+/*
+ * The Python Imaging Library
+ * $Id: Filter.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * apply convolution kernel to image
+ *
+ * history:
+ * 1995-11-26 fl Created, supports 3x3 kernels
+ * 1995-11-27 fl Added 5x5 kernels, copy border
+ * 1999-07-26 fl Eliminated a few compiler warnings
+ * 2002-06-09 fl Moved kernel definitions to Python
+ * 2002-06-11 fl Support floating point kernels
+ * 2003-09-15 fl Added ImagingExpand helper
+ *
+ * Copyright (c) Secret Labs AB 1997-2002. All rights reserved.
+ * Copyright (c) Fredrik Lundh 1995.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+/*
+ * FIXME: Support RGB and RGBA/CMYK modes as well
+ * FIXME: Expand image border (current version leaves border as is)
+ * FIXME: Implement image processing gradient filters
+ */
+
+#include "Imaging.h"
+
+Imaging
+ImagingExpand(Imaging imIn, int xmargin, int ymargin, int mode)
+{
+ Imaging imOut;
+ int x, y;
+
+ if (xmargin < 0 && ymargin < 0)
+ return (Imaging) ImagingError_ValueError("bad kernel size");
+
+ imOut = ImagingNew(
+ imIn->mode, imIn->xsize+2*xmargin, imIn->ysize+2*ymargin
+ );
+ if (!imOut)
+ return NULL;
+
+#define EXPAND_LINE(type, image, yin, yout) {\
+ for (x = 0; x < xmargin; x++)\
+ imOut->image[yout][x] = imIn->image[yin][0];\
+ for (x = 0; x < imIn->xsize; x++)\
+ imOut->image[yout][x+xmargin] = imIn->image[yin][x];\
+ for (x = 0; x < xmargin; x++)\
+ imOut->image[yout][xmargin+imIn->xsize+x] =\
+ imIn->image[yin][imIn->xsize-1];\
+ }
+
+#define EXPAND(type, image) {\
+ for (y = 0; y < ymargin; y++)\
+ EXPAND_LINE(type, image, 0, y);\
+ for (y = 0; y < imIn->ysize; y++)\
+ EXPAND_LINE(type, image, y, y+ymargin);\
+ for (y = 0; y < ymargin; y++)\
+ EXPAND_LINE(type, image, imIn->ysize-1, ymargin+imIn->ysize+y);\
+ }
+
+ if (imIn->image8) {
+ EXPAND(UINT8, image8);
+ } else {
+ EXPAND(INT32, image32);
+ }
+
+ ImagingCopyInfo(imOut, imIn);
+
+ return imOut;
+}
+
+Imaging
+ImagingFilter(Imaging im, int xsize, int ysize, const FLOAT32* kernel,
+ FLOAT32 offset, FLOAT32 divisor)
+{
+ Imaging imOut;
+ int x, y;
+ FLOAT32 sum;
+
+ if (!im || strcmp(im->mode, "L") != 0)
+ return (Imaging) ImagingError_ModeError();
+
+ if ((xsize != 3 && xsize != 5) || xsize != ysize)
+ return (Imaging) ImagingError_ValueError("bad kernel size");
+
+ imOut = ImagingNew(im->mode, im->xsize, im->ysize);
+ if (!imOut)
+ return NULL;
+
+ /* brute force kernel implementations */
+#define KERNEL3x3(image, kernel, d) ( \
+ (int) image[y+1][x-d] * kernel[0] + \
+ (int) image[y+1][x] * kernel[1] + \
+ (int) image[y+1][x+d] * kernel[2] + \
+ (int) image[y][x-d] * kernel[3] + \
+ (int) image[y][x] * kernel[4] + \
+ (int) image[y][x+d] * kernel[5] + \
+ (int) image[y-1][x-d] * kernel[6] + \
+ (int) image[y-1][x] * kernel[7] + \
+ (int) image[y-1][x+d] * kernel[8])
+
+#define KERNEL5x5(image, kernel, d) ( \
+ (int) image[y+2][x-d-d] * kernel[0] + \
+ (int) image[y+2][x-d] * kernel[1] + \
+ (int) image[y+2][x] * kernel[2] + \
+ (int) image[y+2][x+d] * kernel[3] + \
+ (int) image[y+2][x+d+d] * kernel[4] + \
+ (int) image[y+1][x-d-d] * kernel[5] + \
+ (int) image[y+1][x-d] * kernel[6] + \
+ (int) image[y+1][x] * kernel[7] + \
+ (int) image[y+1][x+d] * kernel[8] + \
+ (int) image[y+1][x+d+d] * kernel[9] + \
+ (int) image[y][x-d-d] * kernel[10] + \
+ (int) image[y][x-d] * kernel[11] + \
+ (int) image[y][x] * kernel[12] + \
+ (int) image[y][x+d] * kernel[13] + \
+ (int) image[y][x+d+d] * kernel[14] + \
+ (int) image[y-1][x-d-d] * kernel[15] + \
+ (int) image[y-1][x-d] * kernel[16] + \
+ (int) image[y-1][x] * kernel[17] + \
+ (int) image[y-1][x+d] * kernel[18] + \
+ (int) image[y-1][x+d+d] * kernel[19] + \
+ (int) image[y-2][x-d-d] * kernel[20] + \
+ (int) image[y-2][x-d] * kernel[21] + \
+ (int) image[y-2][x] * kernel[22] + \
+ (int) image[y-2][x+d] * kernel[23] + \
+ (int) image[y-2][x+d+d] * kernel[24])
+
+ if (xsize == 3) {
+ /* 3x3 kernel. */
+ for (x = 0; x < im->xsize; x++)
+ imOut->image[0][x] = im->image8[0][x];
+ for (y = 1; y < im->ysize-1; y++) {
+ imOut->image[y][0] = im->image8[y][0];
+ for (x = 1; x < im->xsize-1; x++) {
+ sum = KERNEL3x3(im->image8, kernel, 1) / divisor + offset;
+ if (sum <= 0)
+ imOut->image8[y][x] = 0;
+ else if (sum >= 255)
+ imOut->image8[y][x] = 255;
+ else
+ imOut->image8[y][x] = (UINT8) sum;
+ }
+ imOut->image8[y][x] = im->image8[y][x];
+ }
+ for (x = 0; x < im->xsize; x++)
+ imOut->image8[y][x] = im->image8[y][x];
+ } else {
+ /* 5x5 kernel. */
+ for (y = 0; y < 2; y++)
+ for (x = 0; x < im->xsize; x++)
+ imOut->image8[y][x] = im->image8[y][x];
+ for (; y < im->ysize-2; y++) {
+ for (x = 0; x < 2; x++)
+ imOut->image8[y][x] = im->image8[y][x];
+ for (; x < im->xsize-2; x++) {
+ sum = KERNEL5x5(im->image8, kernel, 1) / divisor + offset;
+ if (sum <= 0)
+ imOut->image8[y][x] = 0;
+ else if (sum >= 255)
+ imOut->image8[y][x] = 255;
+ else
+ imOut->image8[y][x] = (UINT8) sum;
+ }
+ for (; x < im->xsize; x++)
+ imOut->image8[y][x] = im->image8[y][x];
+ }
+ for (; y < im->ysize; y++)
+ for (x = 0; x < im->xsize; x++)
+ imOut->image8[y][x] = im->image8[y][x];
+ }
+ return imOut;
+}
+
diff --git a/Imaging/libImaging/FliDecode.c b/Imaging/libImaging/FliDecode.c
new file mode 100644
index 0000000..b71ede6
--- /dev/null
+++ b/Imaging/libImaging/FliDecode.c
@@ -0,0 +1,205 @@
+/*
+ * The Python Imaging Library.
+ * $Id: FliDecode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * decoder for Autodesk Animator FLI/FLC animations
+ *
+ * history:
+ * 97-01-03 fl Created
+ * 97-01-17 fl Added SS2 support (FLC)
+ *
+ * Copyright (c) Fredrik Lundh 1997.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+#define I16(ptr)\
+ ((ptr)[0] + ((ptr)[1] << 8))
+
+#define I32(ptr)\
+ ((ptr)[0] + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24))
+
+
+int
+ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ UINT8* ptr;
+ int framesize;
+ int c, chunks;
+ int l, lines;
+ int i, j, x = 0, y, ymax;
+
+ /* If not even the chunk size is present, we'd better leave */
+
+ if (bytes < 4)
+ return 0;
+
+ /* We don't decode anything unless we have a full chunk in the
+ input buffer (on the other hand, the Python part of the driver
+ makes sure this is always the case) */
+
+ ptr = buf;
+
+ framesize = I32(ptr);
+ if (framesize < I32(ptr))
+ return 0;
+
+ /* Make sure this is a frame chunk. The Python driver takes
+ case of other chunk types. */
+
+ if (I16(ptr+4) != 0xF1FA) {
+ state->errcode = IMAGING_CODEC_UNKNOWN;
+ return -1;
+ }
+
+ chunks = I16(ptr+6);
+ ptr += 16;
+
+ /* Process subchunks */
+ for (c = 0; c < chunks; c++) {
+ UINT8 *data = ptr + 6;
+ switch (I16(ptr+4)) {
+ case 4: case 11:
+ /* FLI COLOR chunk */
+ break; /* ignored; handled by Python code */
+ case 7:
+ /* FLI SS2 chunk (word delta) */
+ lines = I16(data); data += 2;
+ for (l = y = 0; l < lines && y < state->ysize; l++, y++) {
+ UINT8* buf = (UINT8*) im->image[y];
+ int p, packets;
+ packets = I16(data); data += 2;
+ while (packets & 0x8000) {
+ /* flag word */
+ if (packets & 0x4000) {
+ y += 65536 - packets; /* skip lines */
+ if (y >= state->ysize) {
+ state->errcode = IMAGING_CODEC_OVERRUN;
+ return -1;
+ }
+ buf = (UINT8*) im->image[y];
+ } else {
+ /* store last byte (used if line width is odd) */
+ buf[state->xsize-1] = (UINT8) packets;
+ }
+ packets = I16(data); data += 2;
+ }
+ for (p = x = 0; p < packets; p++) {
+ x += data[0]; /* pixel skip */
+ if (data[1] >= 128) {
+ i = 256-data[1]; /* run */
+ if (x + i + i > state->xsize)
+ break;
+ for (j = 0; j < i; j++) {
+ buf[x++] = data[2];
+ buf[x++] = data[3];
+ }
+ data += 2 + 2;
+ } else {
+ i = 2 * (int) data[1]; /* chunk */
+ if (x + i > state->xsize)
+ break;
+ memcpy(buf + x, data + 2, i);
+ data += 2 + i;
+ x += i;
+ }
+ }
+ if (p < packets)
+ break; /* didn't process all packets */
+ }
+ if (l < lines) {
+ /* didn't process all lines */
+ state->errcode = IMAGING_CODEC_OVERRUN;
+ return -1;
+ }
+ break;
+ case 12:
+ /* FLI LC chunk (byte delta) */
+ y = I16(data); ymax = y + I16(data+2); data += 4;
+ for (; y < ymax && y < state->ysize; y++) {
+ UINT8* out = (UINT8*) im->image[y];
+ int p, packets = *data++;
+ for (p = x = 0; p < packets; p++, x += i) {
+ x += data[0]; /* skip pixels */
+ if (data[1] & 0x80) {
+ i = 256-data[1]; /* run */
+ if (x + i > state->xsize)
+ break;
+ memset(out + x, data[2], i);
+ data += 3;
+ } else {
+ i = data[1]; /* chunk */
+ if (x + i > state->xsize)
+ break;
+ memcpy(out + x, data + 2, i);
+ data += i + 2;
+ }
+ }
+ if (p < packets)
+ break; /* didn't process all packets */
+ }
+ if (y < ymax) {
+ /* didn't process all lines */
+ state->errcode = IMAGING_CODEC_OVERRUN;
+ return -1;
+ }
+ break;
+ case 13:
+ /* FLI BLACK chunk */
+ for (y = 0; y < state->ysize; y++)
+ memset(im->image[y], 0, state->xsize);
+ break;
+ case 15:
+ /* FLI BRUN chunk */
+ for (y = 0; y < state->ysize; y++) {
+ UINT8* out = (UINT8*) im->image[y];
+ data += 1; /* ignore packetcount byte */
+ for (x = 0; x < state->xsize; x += i) {
+ if (data[0] & 0x80) {
+ i = 256 - data[0];
+ if (x + i > state->xsize)
+ break; /* safety first */
+ memcpy(out + x, data + 1, i);
+ data += i + 1;
+ } else {
+ i = data[0];
+ if (x + i > state->xsize)
+ break; /* safety first */
+ memset(out + x, data[1], i);
+ data += 2;
+ }
+ }
+ if (x != state->xsize) {
+ /* didn't unpack whole line */
+ state->errcode = IMAGING_CODEC_OVERRUN;
+ return -1;
+ }
+ }
+ break;
+ case 16:
+ /* COPY chunk */
+ for (y = 0; y < state->ysize; y++) {
+ UINT8* buf = (UINT8*) im->image[y];
+ memcpy(buf+x, data, state->xsize);
+ data += state->xsize;
+ }
+ break;
+ case 18:
+ /* PSTAMP chunk */
+ break; /* ignored */
+ default:
+ /* unknown chunk */
+ /* printf("unknown FLI/FLC chunk: %d\n", I16(ptr+4)); */
+ state->errcode = IMAGING_CODEC_UNKNOWN;
+ return -1;
+ }
+ ptr += I32(ptr);
+ }
+
+ return -1; /* end of frame */
+}
diff --git a/Imaging/libImaging/Geometry.c b/Imaging/libImaging/Geometry.c
new file mode 100644
index 0000000..6b623df
--- /dev/null
+++ b/Imaging/libImaging/Geometry.c
@@ -0,0 +1,957 @@
+/*
+ * The Python Imaging Library
+ * $Id: Geometry.c 2308 2005-03-02 12:00:55Z fredrik $
+ *
+ * the imaging geometry methods
+ *
+ * history:
+ * 1995-06-15 fl Created
+ * 1996-04-15 fl Changed origin
+ * 1996-05-18 fl Fixed rotate90/270 for rectangular images
+ * 1996-05-27 fl Added general purpose transform
+ * 1996-11-22 fl Don't crash when resizing from outside source image
+ * 1997-08-09 fl Fixed rounding error in resize
+ * 1998-09-21 fl Incorporated transformation patches (from Zircon #2)
+ * 1998-09-22 fl Added bounding box to transform engines
+ * 1999-02-03 fl Fixed bicubic filtering for RGB images
+ * 1999-02-16 fl Added fixed-point version of affine transform
+ * 2001-03-28 fl Fixed transform(EXTENT) for xoffset < 0
+ * 2003-03-10 fl Compiler tweaks
+ * 2004-09-19 fl Fixed bilinear/bicubic filtering of LA images
+ *
+ * Copyright (c) 1997-2003 by Secret Labs AB
+ * Copyright (c) 1995-1997 by Fredrik Lundh
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+#include "Imaging.h"
+
+/* Undef if you don't need resampling filters */
+#define WITH_FILTERS
+
+#define COORD(v) ((v) < 0.0 ? -1 : ((int)(v)))
+#define FLOOR(v) ((v) < 0.0 ? ((int)floor(v)) : ((int)(v)))
+
+/* -------------------------------------------------------------------- */
+/* Transpose operations */
+
+Imaging
+ImagingFlipLeftRight(Imaging imOut, Imaging imIn)
+{
+ ImagingSectionCookie cookie;
+ int x, y, xr;
+
+ if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0)
+ return (Imaging) ImagingError_ModeError();
+ if (imIn->xsize != imOut->xsize || imIn->ysize != imOut->ysize)
+ return (Imaging) ImagingError_Mismatch();
+
+ ImagingCopyInfo(imOut, imIn);
+
+#define FLIP_HORIZ(image)\
+ for (y = 0; y < imIn->ysize; y++) {\
+ xr = imIn->xsize-1;\
+ for (x = 0; x < imIn->xsize; x++, xr--)\
+ imOut->image[y][x] = imIn->image[y][xr];\
+ }
+
+ ImagingSectionEnter(&cookie);
+
+ if (imIn->image8)
+ FLIP_HORIZ(image8)
+ else
+ FLIP_HORIZ(image32)
+
+ ImagingSectionLeave(&cookie);
+
+ return imOut;
+}
+
+
+Imaging
+ImagingFlipTopBottom(Imaging imOut, Imaging imIn)
+{
+ ImagingSectionCookie cookie;
+ int y, yr;
+
+ if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0)
+ return (Imaging) ImagingError_ModeError();
+ if (imIn->xsize != imOut->xsize || imIn->ysize != imOut->ysize)
+ return (Imaging) ImagingError_Mismatch();
+
+ ImagingCopyInfo(imOut, imIn);
+
+ ImagingSectionEnter(&cookie);
+
+ yr = imIn->ysize-1;
+ for (y = 0; y < imIn->ysize; y++, yr--)
+ memcpy(imOut->image[yr], imIn->image[y], imIn->linesize);
+
+ ImagingSectionLeave(&cookie);
+
+ return imOut;
+}
+
+
+Imaging
+ImagingRotate90(Imaging imOut, Imaging imIn)
+{
+ ImagingSectionCookie cookie;
+ int x, y, xr;
+
+ if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0)
+ return (Imaging) ImagingError_ModeError();
+ if (imIn->xsize != imOut->ysize || imIn->ysize != imOut->xsize)
+ return (Imaging) ImagingError_Mismatch();
+
+ ImagingCopyInfo(imOut, imIn);
+
+#define ROTATE_90(image)\
+ for (y = 0; y < imIn->ysize; y++) {\
+ xr = imIn->xsize-1;\
+ for (x = 0; x < imIn->xsize; x++, xr--)\
+ imOut->image[xr][y] = imIn->image[y][x];\
+ }
+
+ ImagingSectionEnter(&cookie);
+
+ if (imIn->image8)
+ ROTATE_90(image8)
+ else
+ ROTATE_90(image32)
+
+ ImagingSectionLeave(&cookie);
+
+ return imOut;
+}
+
+
+Imaging
+ImagingRotate180(Imaging imOut, Imaging imIn)
+{
+ ImagingSectionCookie cookie;
+ int x, y, xr, yr;
+
+ if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0)
+ return (Imaging) ImagingError_ModeError();
+ if (imIn->xsize != imOut->xsize || imIn->ysize != imOut->ysize)
+ return (Imaging) ImagingError_Mismatch();
+
+ ImagingCopyInfo(imOut, imIn);
+
+ yr = imIn->ysize-1;
+
+#define ROTATE_180(image)\
+ for (y = 0; y < imIn->ysize; y++, yr--) {\
+ xr = imIn->xsize-1;\
+ for (x = 0; x < imIn->xsize; x++, xr--)\
+ imOut->image[y][x] = imIn->image[yr][xr];\
+ }
+
+ ImagingSectionEnter(&cookie);
+
+ if (imIn->image8)
+ ROTATE_180(image8)
+ else
+ ROTATE_180(image32)
+
+ ImagingSectionLeave(&cookie);
+
+ return imOut;
+}
+
+
+Imaging
+ImagingRotate270(Imaging imOut, Imaging imIn)
+{
+ ImagingSectionCookie cookie;
+ int x, y, yr;
+
+ if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0)
+ return (Imaging) ImagingError_ModeError();
+ if (imIn->xsize != imOut->ysize || imIn->ysize != imOut->xsize)
+ return (Imaging) ImagingError_Mismatch();
+
+ ImagingCopyInfo(imOut, imIn);
+
+ yr = imIn->ysize - 1;
+
+#define ROTATE_270(image)\
+ for (y = 0; y < imIn->ysize; y++, yr--)\
+ for (x = 0; x < imIn->xsize; x++)\
+ imOut->image[x][y] = imIn->image[yr][x];
+
+ ImagingSectionEnter(&cookie);
+
+ if (imIn->image8)
+ ROTATE_270(image8)
+ else
+ ROTATE_270(image32)
+
+ ImagingSectionLeave(&cookie);
+
+ return imOut;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Transforms */
+
+/* transform primitives (ImagingTransformMap) */
+
+static int
+affine_transform(double* xin, double* yin, int x, int y, void* data)
+{
+ /* full moon tonight. your compiler will generate bogus code
+ for simple expressions, unless you reorganize the code, or
+ install Service Pack 3 */
+
+ double* a = (double*) data;
+ double a0 = a[0]; double a1 = a[1]; double a2 = a[2];
+ double a3 = a[3]; double a4 = a[4]; double a5 = a[5];
+
+ xin[0] = a0 + a1*x + a2*y;
+ yin[0] = a3 + a4*x + a5*y;
+
+ return 1;
+}
+
+static int
+perspective_transform(double* xin, double* yin, int x, int y, void* data)
+{
+ double* a = (double*) data;
+ double a0 = a[0]; double a1 = a[1]; double a2 = a[2];
+ double a3 = a[3]; double a4 = a[4]; double a5 = a[5];
+ double a6 = a[6]; double a7 = a[7];
+
+ xin[0] = (a0 + a1*x + a2*y) / (a6*x + a7*y + 1);
+ yin[0] = (a3 + a4*x + a5*y) / (a6*x + a7*y + 1);
+
+ return 1;
+}
+
+static int
+quadratic_transform(double* xin, double* yin, int x, int y, void* data)
+{
+ double* a = (double*) data;
+
+ double a0 = a[0]; double a1 = a[1]; double a2 = a[2]; double a3 = a[3];
+ double a4 = a[4]; double a5 = a[5]; double a6 = a[6]; double a7 = a[7];
+ double a8 = a[8]; double a9 = a[9]; double a10 = a[10]; double a11 = a[11];
+
+ xin[0] = a0 + a1*x + a2*y + a3*x*x + a4*x*y + a5*y*y;
+ yin[0] = a6 + a7*x + a8*y + a9*x*x + a10*x*y + a11*y*y;
+
+ return 1;
+}
+
+static int
+quad_transform(double* xin, double* yin, int x, int y, void* data)
+{
+ /* quad warp: map quadrilateral to rectangle */
+
+ double* a = (double*) data;
+ double a0 = a[0]; double a1 = a[1]; double a2 = a[2]; double a3 = a[3];
+ double a4 = a[4]; double a5 = a[5]; double a6 = a[6]; double a7 = a[7];
+
+ xin[0] = a0 + a1*x + a2*y + a3*x*y;
+ yin[0] = a4 + a5*x + a6*y + a7*x*y;
+
+ return 1;
+}
+
+/* transform filters (ImagingTransformFilter) */
+
+#ifdef WITH_FILTERS
+
+static int
+nearest_filter8(void* out, Imaging im, double xin, double yin, void* data)
+{
+ int x = COORD(xin);
+ int y = COORD(yin);
+ if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
+ return 0;
+ ((UINT8*)out)[0] = im->image8[y][x];
+ return 1;
+}
+
+static int
+nearest_filter16(void* out, Imaging im, double xin, double yin, void* data)
+{
+ int x = COORD(xin);
+ int y = COORD(yin);
+ if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
+ return 0;
+ ((INT16*)out)[0] = ((INT16*)(im->image8[y]))[x];
+ return 1;
+}
+
+static int
+nearest_filter32(void* out, Imaging im, double xin, double yin, void* data)
+{
+ int x = COORD(xin);
+ int y = COORD(yin);
+ if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
+ return 0;
+ ((INT32*)out)[0] = im->image32[y][x];
+ return 1;
+}
+
+#define XCLIP(im, x) ( ((x) < 0) ? 0 : ((x) < im->xsize) ? (x) : im->xsize-1 )
+#define YCLIP(im, y) ( ((y) < 0) ? 0 : ((y) < im->ysize) ? (y) : im->ysize-1 )
+
+#define BILINEAR(v, a, b, d)\
+ (v = (a) + ( (b) - (a) ) * (d))
+
+#define BILINEAR_HEAD(type)\
+ int x, y;\
+ int x0, x1;\
+ double v1, v2;\
+ double dx, dy;\
+ type* in;\
+ if (xin < 0.0 || xin >= im->xsize || yin < 0.0 || yin >= im->ysize)\
+ return 0;\
+ xin -= 0.5;\
+ yin -= 0.5;\
+ x = FLOOR(xin);\
+ y = FLOOR(yin);\
+ dx = xin - x;\
+ dy = yin - y;
+
+#define BILINEAR_BODY(type, image, step, offset) {\
+ in = (type*) ((image)[YCLIP(im, y)] + offset);\
+ x0 = XCLIP(im, x+0)*step;\
+ x1 = XCLIP(im, x+1)*step;\
+ BILINEAR(v1, in[x0], in[x1], dx);\
+ if (y+1 >= 0 && y+1 < im->ysize) {\
+ in = (type*) ((image)[y+1] + offset);\
+ BILINEAR(v2, in[x0], in[x1], dx);\
+ } else\
+ v2 = v1;\
+ BILINEAR(v1, v1, v2, dy);\
+}
+
+static int
+bilinear_filter8(void* out, Imaging im, double xin, double yin, void* data)
+{
+ BILINEAR_HEAD(UINT8);
+ BILINEAR_BODY(UINT8, im->image8, 1, 0);
+ ((UINT8*)out)[0] = (UINT8) v1;
+ return 1;
+}
+
+static int
+bilinear_filter32I(void* out, Imaging im, double xin, double yin, void* data)
+{
+ BILINEAR_HEAD(INT32);
+ BILINEAR_BODY(INT32, im->image32, 1, 0);
+ ((INT32*)out)[0] = (INT32) v1;
+ return 1;
+}
+
+static int
+bilinear_filter32F(void* out, Imaging im, double xin, double yin, void* data)
+{
+ BILINEAR_HEAD(FLOAT32);
+ BILINEAR_BODY(FLOAT32, im->image32, 1, 0);
+ ((FLOAT32*)out)[0] = (FLOAT32) v1;
+ return 1;
+}
+
+static int
+bilinear_filter32LA(void* out, Imaging im, double xin, double yin, void* data)
+{
+ BILINEAR_HEAD(UINT8);
+ BILINEAR_BODY(UINT8, im->image, 4, 0);
+ ((UINT8*)out)[0] = (UINT8) v1;
+ ((UINT8*)out)[1] = (UINT8) v1;
+ ((UINT8*)out)[2] = (UINT8) v1;
+ BILINEAR_BODY(UINT8, im->image, 4, 3);
+ ((UINT8*)out)[3] = (UINT8) v1;
+ return 1;
+}
+
+static int
+bilinear_filter32RGB(void* out, Imaging im, double xin, double yin, void* data)
+{
+ int b;
+ BILINEAR_HEAD(UINT8);
+ for (b = 0; b < im->bands; b++) {
+ BILINEAR_BODY(UINT8, im->image, 4, b);
+ ((UINT8*)out)[b] = (UINT8) v1;
+ }
+ return 1;
+}
+
+#define BICUBIC(v, v1, v2, v3, v4, d) {\
+ double p1 = v2;\
+ double p2 = -v1 + v3;\
+ double p3 = 2*(v1 - v2) + v3 - v4;\
+ double p4 = -v1 + v2 - v3 + v4;\
+ v = p1 + (d)*(p2 + (d)*(p3 + (d)*p4));\
+}
+
+#define BICUBIC_HEAD(type)\
+ int x = FLOOR(xin);\
+ int y = FLOOR(yin);\
+ int x0, x1, x2, x3;\
+ double v1, v2, v3, v4;\
+ double dx, dy;\
+ type* in;\
+ if (xin < 0.0 || xin >= im->xsize || yin < 0.0 || yin >= im->ysize)\
+ return 0;\
+ xin -= 0.5;\
+ yin -= 0.5;\
+ x = FLOOR(xin);\
+ y = FLOOR(yin);\
+ dx = xin - x;\
+ dy = yin - y;\
+ x--; y--;
+
+#define BICUBIC_BODY(type, image, step, offset) {\
+ in = (type*) ((image)[YCLIP(im, y)] + offset);\
+ x0 = XCLIP(im, x+0)*step;\
+ x1 = XCLIP(im, x+1)*step;\
+ x2 = XCLIP(im, x+2)*step;\
+ x3 = XCLIP(im, x+3)*step;\
+ BICUBIC(v1, in[x0], in[x1], in[x2], in[x3], dx);\
+ if (y+1 >= 0 && y+1 < im->ysize) {\
+ in = (type*) ((image)[y+1] + offset);\
+ BICUBIC(v2, in[x0], in[x1], in[x2], in[x3], dx);\
+ } else\
+ v2 = v1;\
+ if (y+2 >= 0 && y+2 < im->ysize) {\
+ in = (type*) ((image)[y+2] + offset);\
+ BICUBIC(v3, in[x0], in[x1], in[x2], in[x3], dx);\
+ } else\
+ v3 = v2;\
+ if (y+3 >= 0 && y+3 < im->ysize) {\
+ in = (type*) ((image)[y+3] + offset);\
+ BICUBIC(v4, in[x0], in[x1], in[x2], in[x3], dx);\
+ } else\
+ v4 = v3;\
+ BICUBIC(v1, v1, v2, v3, v4, dy);\
+}
+
+
+static int
+bicubic_filter8(void* out, Imaging im, double xin, double yin, void* data)
+{
+ BICUBIC_HEAD(UINT8);
+ BICUBIC_BODY(UINT8, im->image8, 1, 0);
+ if (v1 <= 0.0)
+ ((UINT8*)out)[0] = 0;
+ else if (v1 >= 255.0)
+ ((UINT8*)out)[0] = 255;
+ else
+ ((UINT8*)out)[0] = (UINT8) v1;
+ return 1;
+}
+
+static int
+bicubic_filter32I(void* out, Imaging im, double xin, double yin, void* data)
+{
+ BICUBIC_HEAD(INT32);
+ BICUBIC_BODY(INT32, im->image32, 1, 0);
+ ((INT32*)out)[0] = (INT32) v1;
+ return 1;
+}
+
+static int
+bicubic_filter32F(void* out, Imaging im, double xin, double yin, void* data)
+{
+ BICUBIC_HEAD(FLOAT32);
+ BICUBIC_BODY(FLOAT32, im->image32, 1, 0);
+ ((FLOAT32*)out)[0] = (FLOAT32) v1;
+ return 1;
+}
+
+static int
+bicubic_filter32LA(void* out, Imaging im, double xin, double yin, void* data)
+{
+ BICUBIC_HEAD(UINT8);
+ BICUBIC_BODY(UINT8, im->image, 4, 0);
+ if (v1 <= 0.0) {
+ ((UINT8*)out)[0] = 0;
+ ((UINT8*)out)[1] = 0;
+ ((UINT8*)out)[2] = 0;
+ } else if (v1 >= 255.0) {
+ ((UINT8*)out)[0] = 255;
+ ((UINT8*)out)[1] = 255;
+ ((UINT8*)out)[2] = 255;
+ } else {
+ ((UINT8*)out)[0] = (UINT8) v1;
+ ((UINT8*)out)[1] = (UINT8) v1;
+ ((UINT8*)out)[2] = (UINT8) v1;
+ }
+ BICUBIC_BODY(UINT8, im->image, 4, 3);
+ if (v1 <= 0.0)
+ ((UINT8*)out)[3] = 0;
+ else if (v1 >= 255.0)
+ ((UINT8*)out)[3] = 255;
+ else
+ ((UINT8*)out)[3] = (UINT8) v1;
+ return 1;
+}
+
+static int
+bicubic_filter32RGB(void* out, Imaging im, double xin, double yin, void* data)
+{
+ int b;
+ BICUBIC_HEAD(UINT8);
+ for (b = 0; b < im->bands; b++) {
+ BICUBIC_BODY(UINT8, im->image, 4, b);
+ if (v1 <= 0.0)
+ ((UINT8*)out)[b] = 0;
+ else if (v1 >= 255.0)
+ ((UINT8*)out)[b] = 255;
+ else
+ ((UINT8*)out)[b] = (UINT8) v1;
+ }
+ return 1;
+}
+
+static ImagingTransformFilter
+getfilter(Imaging im, int filterid)
+{
+ switch (filterid) {
+ case IMAGING_TRANSFORM_NEAREST:
+ if (im->image8)
+ switch (im->type) {
+ case IMAGING_TYPE_UINT8:
+ return (ImagingTransformFilter) nearest_filter8;
+ case IMAGING_TYPE_SPECIAL:
+ switch (im->pixelsize) {
+ case 1:
+ return (ImagingTransformFilter) nearest_filter8;
+ case 2:
+ return (ImagingTransformFilter) nearest_filter16;
+ case 4:
+ return (ImagingTransformFilter) nearest_filter32;
+ }
+ }
+ else
+ return (ImagingTransformFilter) nearest_filter32;
+ break;
+ case IMAGING_TRANSFORM_BILINEAR:
+ if (im->image8)
+ return (ImagingTransformFilter) bilinear_filter8;
+ else if (im->image32) {
+ switch (im->type) {
+ case IMAGING_TYPE_UINT8:
+ if (im->bands == 2)
+ return (ImagingTransformFilter) bilinear_filter32LA;
+ else
+ return (ImagingTransformFilter) bilinear_filter32RGB;
+ case IMAGING_TYPE_INT32:
+ return (ImagingTransformFilter) bilinear_filter32I;
+ case IMAGING_TYPE_FLOAT32:
+ return (ImagingTransformFilter) bilinear_filter32F;
+ }
+ }
+ break;
+ case IMAGING_TRANSFORM_BICUBIC:
+ if (im->image8)
+ return (ImagingTransformFilter) bicubic_filter8;
+ else if (im->image32) {
+ switch (im->type) {
+ case IMAGING_TYPE_UINT8:
+ if (im->bands == 2)
+ return (ImagingTransformFilter) bicubic_filter32LA;
+ else
+ return (ImagingTransformFilter) bicubic_filter32RGB;
+ case IMAGING_TYPE_INT32:
+ return (ImagingTransformFilter) bicubic_filter32I;
+ case IMAGING_TYPE_FLOAT32:
+ return (ImagingTransformFilter) bicubic_filter32F;
+ }
+ }
+ break;
+ }
+ /* no such filter */
+ return NULL;
+}
+
+#else
+#define getfilter(im, id) NULL
+#endif
+
+/* transformation engines */
+
+Imaging
+ImagingTransform(
+ Imaging imOut, Imaging imIn, int x0, int y0, int x1, int y1,
+ ImagingTransformMap transform, void* transform_data,
+ ImagingTransformFilter filter, void* filter_data,
+ int fill)
+{
+ /* slow generic transformation. use ImagingTransformAffine or
+ ImagingScaleAffine where possible. */
+
+ ImagingSectionCookie cookie;
+ int x, y;
+ char *out;
+ double xx, yy;
+
+ if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0)
+ return (Imaging) ImagingError_ModeError();
+
+ ImagingCopyInfo(imOut, imIn);
+
+ ImagingSectionEnter(&cookie);
+
+ if (x0 < 0)
+ x0 = 0;
+ if (y0 < 0)
+ y0 = 0;
+ if (x1 > imOut->xsize)
+ x1 = imOut->xsize;
+ if (y1 > imOut->ysize)
+ y1 = imOut->ysize;
+
+ for (y = y0; y < y1; y++) {
+ out = imOut->image[y] + x0*imOut->pixelsize;
+ for (x = x0; x < x1; x++) {
+ if (!transform(&xx, &yy, x-x0, y-y0, transform_data) ||
+ !filter(out, imIn, xx, yy, filter_data)) {
+ if (fill)
+ memset(out, 0, imOut->pixelsize);
+ }
+ out += imOut->pixelsize;
+ }
+ }
+
+ ImagingSectionLeave(&cookie);
+
+ return imOut;
+}
+
+static Imaging
+ImagingScaleAffine(Imaging imOut, Imaging imIn,
+ int x0, int y0, int x1, int y1,
+ double a[6], int fill)
+{
+ /* scale, nearest neighbour resampling */
+
+ ImagingSectionCookie cookie;
+ int x, y;
+ int xin;
+ double xo, yo;
+ int xmin, xmax;
+ int *xintab;
+
+ if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0)
+ return (Imaging) ImagingError_ModeError();
+
+ ImagingCopyInfo(imOut, imIn);
+
+ if (x0 < 0)
+ x0 = 0;
+ if (y0 < 0)
+ y0 = 0;
+ if (x1 > imOut->xsize)
+ x1 = imOut->xsize;
+ if (y1 > imOut->ysize)
+ y1 = imOut->ysize;
+
+ xintab = (int*) malloc(imOut->xsize * sizeof(int));
+ if (!xintab) {
+ ImagingDelete(imOut);
+ return (Imaging) ImagingError_MemoryError();
+ }
+
+ xo = a[0];
+ yo = a[3];
+
+ xmin = x1;
+ xmax = x0;
+
+ /* Pretabulate horizontal pixel positions */
+ for (x = x0; x < x1; x++) {
+ xin = COORD(xo);
+ if (xin >= 0 && xin < (int) imIn->xsize) {
+ xmax = x+1;
+ if (x < xmin)
+ xmin = x;
+ xintab[x] = xin;
+ }
+ xo += a[1];
+ }
+
+#define AFFINE_SCALE(pixel, image)\
+ for (y = y0; y < y1; y++) {\
+ int yi = COORD(yo);\
+ pixel *in, *out;\
+ out = imOut->image[y];\
+ if (fill && x1 > x0)\
+ memset(out+x0, 0, (x1-x0)*sizeof(pixel));\
+ if (yi >= 0 && yi < imIn->ysize) {\
+ in = imIn->image[yi];\
+ for (x = xmin; x < xmax; x++)\
+ out[x] = in[xintab[x]];\
+ }\
+ yo += a[5];\
+ }
+
+ ImagingSectionEnter(&cookie);
+
+ if (imIn->image8) {
+ AFFINE_SCALE(UINT8, image8);
+ } else {
+ AFFINE_SCALE(INT32, image32);
+ }
+
+ ImagingSectionLeave(&cookie);
+
+ free(xintab);
+
+ return imOut;
+}
+
+static inline int
+check_fixed(double a[6], int x, int y)
+{
+ return (fabs(a[0] + x*a[1] + y*a[2]) < 32768.0 &&
+ fabs(a[3] + x*a[4] + y*a[5]) < 32768.0);
+}
+
+static inline Imaging
+affine_fixed(Imaging imOut, Imaging imIn,
+ int x0, int y0, int x1, int y1,
+ double a[6], int filterid, int fill)
+{
+ /* affine transform, nearest neighbour resampling, fixed point
+ arithmetics */
+
+ int x, y;
+ int xin, yin;
+ int xsize, ysize;
+ int xx, yy;
+ int a0, a1, a2, a3, a4, a5;
+
+ ImagingCopyInfo(imOut, imIn);
+
+ xsize = (int) imIn->xsize;
+ ysize = (int) imIn->ysize;
+
+/* use 16.16 fixed point arithmetics */
+#define FIX(v) FLOOR((v)*65536.0 + 0.5)
+
+ a0 = FIX(a[0]); a1 = FIX(a[1]); a2 = FIX(a[2]);
+ a3 = FIX(a[3]); a4 = FIX(a[4]); a5 = FIX(a[5]);
+
+#define AFFINE_TRANSFORM_FIXED(pixel, image)\
+ for (y = y0; y < y1; y++) {\
+ pixel *out;\
+ xx = a0;\
+ yy = a3;\
+ out = imOut->image[y];\
+ if (fill && x1 > x0)\
+ memset(out+x0, 0, (x1-x0)*sizeof(pixel));\
+ for (x = x0; x < x1; x++, out++) {\
+ xin = xx >> 16;\
+ if (xin >= 0 && xin < xsize) {\
+ yin = yy >> 16;\
+ if (yin >= 0 && yin < ysize)\
+ *out = imIn->image[yin][xin];\
+ }\
+ xx += a1;\
+ yy += a4;\
+ }\
+ a0 += a2;\
+ a3 += a5;\
+ }
+
+ if (imIn->image8)
+ AFFINE_TRANSFORM_FIXED(UINT8, image8)
+ else
+ AFFINE_TRANSFORM_FIXED(INT32, image32)
+
+ return imOut;
+}
+
+Imaging
+ImagingTransformAffine(Imaging imOut, Imaging imIn,
+ int x0, int y0, int x1, int y1,
+ double a[6], int filterid, int fill)
+{
+ /* affine transform, nearest neighbour resampling, floating point
+ arithmetics*/
+
+ ImagingSectionCookie cookie;
+ int x, y;
+ int xin, yin;
+ int xsize, ysize;
+ double xx, yy;
+ double xo, yo;
+
+ if (filterid || imIn->type == IMAGING_TYPE_SPECIAL) {
+ /* Filtered transform */
+ ImagingTransformFilter filter = getfilter(imIn, filterid);
+ if (!filter)
+ return (Imaging) ImagingError_ValueError("unknown filter");
+ return ImagingTransform(
+ imOut, imIn,
+ x0, y0, x1, y1,
+ affine_transform, a,
+ filter, NULL, fill);
+ }
+
+ if (a[2] == 0 && a[4] == 0)
+ /* Scaling */
+ return ImagingScaleAffine(imOut, imIn, x0, y0, x1, y1, a, fill);
+
+ if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0)
+ return (Imaging) ImagingError_ModeError();
+
+ if (x0 < 0)
+ x0 = 0;
+ if (y0 < 0)
+ y0 = 0;
+ if (x1 > imOut->xsize)
+ x1 = imOut->xsize;
+ if (y1 > imOut->ysize)
+ y1 = imOut->ysize;
+
+ ImagingCopyInfo(imOut, imIn);
+
+ /* translate all four corners to check if they are within the
+ range that can be represented by the fixed point arithmetics */
+
+ if (check_fixed(a, 0, 0) && check_fixed(a, x1-x0, y1-y0) &&
+ check_fixed(a, 0, y1-y0) && check_fixed(a, x1-x0, 0))
+ return affine_fixed(imOut, imIn, x0, y0, x1, y1, a, filterid, fill);
+
+ /* FIXME: cannot really think of any reasonable case when the
+ following code is used. maybe we should fall back on the slow
+ generic transform engine in this case? */
+
+ xsize = (int) imIn->xsize;
+ ysize = (int) imIn->ysize;
+
+ xo = a[0];
+ yo = a[3];
+
+#define AFFINE_TRANSFORM(pixel, image)\
+ for (y = y0; y < y1; y++) {\
+ pixel *out;\
+ xx = xo;\
+ yy = yo;\
+ out = imOut->image[y];\
+ if (fill && x1 > x0)\
+ memset(out+x0, 0, (x1-x0)*sizeof(pixel));\
+ for (x = x0; x < x1; x++, out++) {\
+ xin = COORD(xx);\
+ if (xin >= 0 && xin < xsize) {\
+ yin = COORD(yy);\
+ if (yin >= 0 && yin < ysize)\
+ *out = imIn->image[yin][xin];\
+ }\
+ xx += a[1];\
+ yy += a[4];\
+ }\
+ xo += a[2];\
+ yo += a[5];\
+ }
+
+ ImagingSectionEnter(&cookie);
+
+ if (imIn->image8)
+ AFFINE_TRANSFORM(UINT8, image8)
+ else
+ AFFINE_TRANSFORM(INT32, image32)
+
+ ImagingSectionLeave(&cookie);
+
+ return imOut;
+}
+
+Imaging
+ImagingTransformPerspective(Imaging imOut, Imaging imIn,
+ int x0, int y0, int x1, int y1,
+ double a[8], int filterid, int fill)
+{
+ ImagingTransformFilter filter = getfilter(imIn, filterid);
+ if (!filter)
+ return (Imaging) ImagingError_ValueError("bad filter number");
+
+ return ImagingTransform(
+ imOut, imIn,
+ x0, y0, x1, y1,
+ perspective_transform, a,
+ filter, NULL,
+ fill);
+}
+
+Imaging
+ImagingTransformQuad(Imaging imOut, Imaging imIn,
+ int x0, int y0, int x1, int y1,
+ double a[8], int filterid, int fill)
+{
+ ImagingTransformFilter filter = getfilter(imIn, filterid);
+ if (!filter)
+ return (Imaging) ImagingError_ValueError("bad filter number");
+
+ return ImagingTransform(
+ imOut, imIn,
+ x0, y0, x1, y1,
+ quad_transform, a,
+ filter, NULL,
+ fill);
+}
+
+/* -------------------------------------------------------------------- */
+/* Convenience functions */
+
+Imaging
+ImagingResize(Imaging imOut, Imaging imIn, int filterid)
+{
+ double a[6];
+
+ if (imOut->xsize == imIn->xsize && imOut->ysize == imIn->ysize)
+ return ImagingCopy2(imOut, imIn);
+
+ memset(a, 0, sizeof a);
+ a[1] = (double) imIn->xsize / imOut->xsize;
+ a[5] = (double) imIn->ysize / imOut->ysize;
+
+ if (!filterid && imIn->type != IMAGING_TYPE_SPECIAL)
+ return ImagingScaleAffine(
+ imOut, imIn,
+ 0, 0, imOut->xsize, imOut->ysize,
+ a, 1);
+
+ return ImagingTransformAffine(
+ imOut, imIn,
+ 0, 0, imOut->xsize, imOut->ysize,
+ a, filterid, 1);
+}
+
+Imaging
+ImagingRotate(Imaging imOut, Imaging imIn, double theta, int filterid)
+{
+ int xsize, ysize;
+ double sintheta, costheta;
+ double a[6];
+
+ /* Setup an affine transform to rotate around the image center */
+ theta = -theta * M_PI / 180.0;
+ sintheta = sin(theta);
+ costheta = cos(theta);
+
+ xsize = imOut->xsize;
+ ysize = imOut->ysize;
+
+ a[0] = -costheta * xsize/2 - sintheta * ysize/2 + xsize/2;
+ a[1] = costheta;
+ a[2] = sintheta;
+ a[3] = sintheta * xsize/2 - costheta * ysize/2 + ysize/2;
+ a[4] = -sintheta;
+ a[5] = costheta;
+
+ return ImagingTransformAffine(
+ imOut, imIn,
+ 0, 0, imOut->xsize, imOut->ysize,
+ a, filterid, 1);
+}
diff --git a/Imaging/libImaging/GetBBox.c b/Imaging/libImaging/GetBBox.c
new file mode 100644
index 0000000..c06d0eb
--- /dev/null
+++ b/Imaging/libImaging/GetBBox.c
@@ -0,0 +1,322 @@
+/*
+ * The Python Imaging Library
+ * $Id: GetBBox.c 2298 2005-02-17 21:17:29Z fredrik $
+ *
+ * helpers to bounding boxes, min/max values, number of colors, etc.
+ *
+ * history:
+ * 1996-07-22 fl Created
+ * 1996-12-30 fl Added projection stuff
+ * 1998-07-12 fl Added extrema stuff
+ * 2004-09-17 fl Added colors stuff
+ *
+ * Copyright (c) 1997-2004 by Secret Labs AB.
+ * Copyright (c) 1996-2004 by Fredrik Lundh.
+ *
+ * See the README file for details on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+int
+ImagingGetBBox(Imaging im, int bbox[4])
+{
+ /* Get the bounding box for any non-zero data in the image.*/
+
+ int x, y;
+ int has_data;
+
+ /* Initialize bounding box to max values */
+ bbox[0] = im->xsize;
+ bbox[1] = -1;
+ bbox[2] = bbox[3] = 0;
+
+#define GETBBOX(image, mask)\
+ for (y = 0; y < im->ysize; y++) {\
+ has_data = 0;\
+ for (x = 0; x < im->xsize; x++)\
+ if (im->image[y][x] & mask) {\
+ has_data = 1;\
+ if (x < bbox[0])\
+ bbox[0] = x;\
+ if (x >= bbox[2])\
+ bbox[2] = x+1;\
+ }\
+ if (has_data) {\
+ if (bbox[1] < 0)\
+ bbox[1] = y;\
+ bbox[3] = y+1;\
+ }\
+ }
+
+ if (im->image8) {
+ GETBBOX(image8, 0xff);
+ } else {
+ INT32 mask = 0xffffffff;
+ if (im->bands == 3)
+ ((UINT8*) &mask)[3] = 0;
+ GETBBOX(image32, mask);
+ }
+
+ /* Check that we got a box */
+ if (bbox[1] < 0)
+ return 0; /* no data */
+
+ return 1; /* ok */
+}
+
+
+int
+ImagingGetProjection(Imaging im, UINT8* xproj, UINT8* yproj)
+{
+ /* Get projection arrays for non-zero data in the image.*/
+
+ int x, y;
+ int has_data;
+
+ /* Initialize projection arrays */
+ memset(xproj, 0, im->xsize);
+ memset(yproj, 0, im->ysize);
+
+#define GETPROJ(image, mask)\
+ for (y = 0; y < im->ysize; y++) {\
+ has_data = 0;\
+ for (x = 0; x < im->xsize; x++)\
+ if (im->image[y][x] & mask) {\
+ has_data = 1;\
+ xproj[x] = 1;\
+ }\
+ if (has_data)\
+ yproj[y] = 1;\
+ }
+
+ if (im->image8) {
+ GETPROJ(image8, 0xff);
+ } else {
+ INT32 mask = 0xffffffff;
+ if (im->bands == 3)
+ ((UINT8*) &mask)[3] = 0;
+ GETPROJ(image32, mask);
+ }
+
+ return 1; /* ok */
+}
+
+
+int
+ImagingGetExtrema(Imaging im, void *extrema)
+{
+ int x, y;
+ INT32 imin, imax;
+ FLOAT32 fmin, fmax;
+
+ if (im->bands != 1) {
+ ImagingError_ModeError();
+ return -1; /* mismatch */
+ }
+
+ if (!im->xsize || !im->ysize)
+ return 0; /* zero size */
+
+ switch (im->type) {
+ case IMAGING_TYPE_UINT8:
+ imin = imax = im->image8[0][0];
+ for (y = 0; y < im->ysize; y++) {
+ UINT8* in = im->image8[y];
+ for (x = 0; x < im->xsize; x++) {
+ if (imin > in[x])
+ imin = in[x];
+ else if (imax < in[x])
+ imax = in[x];
+ }
+ }
+ ((UINT8*) extrema)[0] = (UINT8) imin;
+ ((UINT8*) extrema)[1] = (UINT8) imax;
+ break;
+ case IMAGING_TYPE_INT32:
+ imin = imax = im->image32[0][0];
+ for (y = 0; y < im->ysize; y++) {
+ INT32* in = im->image32[y];
+ for (x = 0; x < im->xsize; x++) {
+ if (imin > in[x])
+ imin = in[x];
+ else if (imax < in[x])
+ imax = in[x];
+ }
+ }
+ ((INT32*) extrema)[0] = imin;
+ ((INT32*) extrema)[1] = imax;
+ break;
+ case IMAGING_TYPE_FLOAT32:
+ fmin = fmax = ((FLOAT32*) im->image32[0])[0];
+ for (y = 0; y < im->ysize; y++) {
+ FLOAT32* in = (FLOAT32*) im->image32[y];
+ for (x = 0; x < im->xsize; x++) {
+ if (fmin > in[x])
+ fmin = in[x];
+ else if (fmax < in[x])
+ fmax = in[x];
+ }
+ }
+ ((FLOAT32*) extrema)[0] = fmin;
+ ((FLOAT32*) extrema)[1] = fmax;
+ break;
+ case IMAGING_TYPE_SPECIAL:
+ if (strcmp(im->mode, "I;16") == 0) {
+ imin = imax = ((UINT16*) im->image8[0])[0];
+ for (y = 0; y < im->ysize; y++) {
+ UINT16* in = (UINT16 *) im->image[y];
+ for (x = 0; x < im->xsize; x++) {
+ if (imin > in[x])
+ imin = in[x];
+ else if (imax < in[x])
+ imax = in[x];
+ }
+ }
+ ((UINT16*) extrema)[0] = (UINT16) imin;
+ ((UINT16*) extrema)[1] = (UINT16) imax;
+ break;
+ }
+ /* FALL THROUGH */
+ default:
+ ImagingError_ModeError();
+ return -1;
+ }
+ return 1; /* ok */
+}
+
+
+/* static ImagingColorItem* getcolors8(Imaging im, int maxcolors, int* size);*/
+static ImagingColorItem* getcolors32(Imaging im, int maxcolors, int* size);
+
+ImagingColorItem*
+ImagingGetColors(Imaging im, int maxcolors, int* size)
+{
+ /* FIXME: add support for 8-bit images */
+ return getcolors32(im, maxcolors, size);
+}
+
+static ImagingColorItem*
+getcolors32(Imaging im, int maxcolors, int* size)
+{
+ unsigned int h;
+ unsigned int i, incr;
+ int colors;
+ INT32 pixel_mask;
+ int x, y;
+ ImagingColorItem* table;
+ ImagingColorItem* v;
+
+ unsigned int code_size;
+ unsigned int code_poly;
+ unsigned int code_mask;
+
+ /* note: the hash algorithm used here is based on the dictionary
+ code in Python 2.1.3; the exact implementation is borrowed from
+ Python's Unicode property database (written by yours truly) /F */
+
+ static int SIZES[] = {
+ 4,3, 8,3, 16,3, 32,5, 64,3, 128,3, 256,29, 512,17, 1024,9, 2048,5,
+ 4096,83, 8192,27, 16384,43, 32768,3, 65536,45, 131072,9, 262144,39,
+ 524288,39, 1048576,9, 2097152,5, 4194304,3, 8388608,33, 16777216,27,
+ 33554432,9, 67108864,71, 134217728,39, 268435456,9, 536870912,5,
+ 1073741824,83, 0
+ };
+
+ code_size = code_poly = code_mask = 0;
+
+ for (i = 0; SIZES[i]; i += 2) {
+ if (SIZES[i] > maxcolors) {
+ code_size = SIZES[i];
+ code_poly = SIZES[i+1];
+ code_mask = code_size - 1;
+ break;
+ }
+ }
+
+ /* printf("code_size=%d\n", code_size); */
+ /* printf("code_poly=%d\n", code_poly); */
+
+ if (!code_size) {
+ ImagingError_MemoryError(); /* just give up */
+ return NULL;
+ }
+
+ if (!im->image32) {
+ ImagingError_ModeError();
+ return NULL;
+ }
+
+ table = calloc(code_size + 1, sizeof(ImagingColorItem));
+ if (!table) {
+ ImagingError_MemoryError();
+ return NULL;
+ }
+
+ pixel_mask = 0xffffffff;
+ if (im->bands == 3)
+ ((UINT8*) &pixel_mask)[3] = 0;
+
+ colors = 0;
+
+ for (y = 0; y < im->ysize; y++) {
+ INT32* p = im->image32[y];
+ for (x = 0; x < im->xsize; x++) {
+ INT32 pixel = p[x] & pixel_mask;
+ h = (pixel); /* null hashing */
+ i = (~h) & code_mask;
+ v = &table[i];
+ if (!v->count) {
+ /* add to table */
+ if (colors++ == maxcolors)
+ goto overflow;
+ v->x = x; v->y = y;
+ v->pixel = pixel;
+ v->count = 1;
+ continue;
+ } else if (v->pixel == pixel) {
+ v->count++;
+ continue;
+ }
+ incr = (h ^ (h >> 3)) & code_mask;
+ if (!incr)
+ incr = code_mask;
+ for (;;) {
+ i = (i + incr) & code_mask;
+ v = &table[i];
+ if (!v->count) {
+ /* add to table */
+ if (colors++ == maxcolors)
+ goto overflow;
+ v->x = x; v->y = y;
+ v->pixel = pixel;
+ v->count = 1;
+ break;
+ } else if (v->pixel == pixel) {
+ v->count++;
+ break;
+ }
+ incr = incr << 1;
+ if (incr > code_mask)
+ incr = incr ^ code_poly;
+ }
+ }
+ }
+
+overflow:
+
+ /* pack the table */
+ for (x = y = 0; x < (int) code_size; x++)
+ if (table[x].count) {
+ if (x != y)
+ table[y] = table[x];
+ y++;
+ }
+ table[y].count = 0; /* mark end of table */
+
+ *size = colors;
+
+ return table;
+}
diff --git a/Imaging/libImaging/Gif.h b/Imaging/libImaging/Gif.h
new file mode 100644
index 0000000..8957c39
--- /dev/null
+++ b/Imaging/libImaging/Gif.h
@@ -0,0 +1,109 @@
+/*
+ * The Python Imaging Library.
+ * $Id: Gif.h 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * Declarations for a fast, suspendable GIF decoder.
+ *
+ * Copyright (c) Fredrik Lundh 1995-96.
+ */
+
+
+/* Max size for a LZW code word. */
+
+#define GIFBITS 12
+
+#define GIFTABLE (1<<GIFBITS)
+#define GIFBUFFER (1<<GIFBITS)
+
+
+typedef struct {
+
+ /* CONFIGURATION */
+
+ /* Initial number of bits. The caller should clear all fields in
+ this structure and set this field before calling the decoder
+ the first time. */
+ int bits;
+
+ /* If set, this is an interlaced image. Process it the following way:
+ * 1st pass: start at top line, lines are 8 pixels high, step 8 pixels
+ * 2nd pass: start at line 4, lines are 4 pixels high, step 8 pixels
+ * 3rd pass: start at line 2, lines are 2 pixels high, step 4 pixels
+ * 4th pass: start at line 1, lines are 1 pixels high, step 2 pixels
+ */
+ int interlace;
+
+ /* PRIVATE CONTEXT (set by decoder) */
+
+ /* Interlace parameters */
+ int step, repeat;
+
+ /* Input bit buffer */
+ INT32 bitbuffer;
+ int bitcount;
+ int blocksize;
+
+ /* Code buffer */
+ int codesize;
+ int codemask;
+
+ /* Constant symbol codes */
+ int clear, end;
+
+ /* Symbol history */
+ int lastcode;
+ unsigned char lastdata;
+
+ /* History buffer */
+ int bufferindex;
+ unsigned char buffer[GIFTABLE];
+
+ /* Symbol table */
+ unsigned INT16 link[GIFTABLE];
+ unsigned char data[GIFTABLE];
+ int next;
+
+} GIFDECODERSTATE;
+
+typedef struct GIFENCODERBLOCK_T
+{
+ struct GIFENCODERBLOCK_T *next;
+ int size;
+ UINT8 data[255];
+} GIFENCODERBLOCK;
+
+typedef struct {
+
+ /* CONFIGURATION */
+
+ /* Initial number of bits. The caller should clear all fields in
+ this structure and set this field before calling the encoder
+ the first time. */
+ int bits;
+
+ /* NOTE: the expanding encoder ignores this field */
+
+ /* If set, write an interlaced image (see above) */
+ int interlace;
+
+ /* PRIVATE CONTEXT (set by encoder) */
+
+ /* Interlace parameters */
+ int step, repeat;
+
+ /* Output bit buffer */
+ INT32 bitbuffer;
+ int bitcount;
+
+ /* Output buffer list (linked list) */
+ GIFENCODERBLOCK* block; /* current block */
+ GIFENCODERBLOCK* flush; /* output queue */
+ GIFENCODERBLOCK* free; /* if not null, use this */
+
+ /* Fields used for run-length encoding */
+ int first; /* true if we haven't read the first pixel */
+ int last; /* last byte value seen */
+ int count; /* how many bytes with that value we've seen */
+ int lastcode;
+
+} GIFENCODERSTATE;
diff --git a/Imaging/libImaging/GifDecode.c b/Imaging/libImaging/GifDecode.c
new file mode 100644
index 0000000..d97c276
--- /dev/null
+++ b/Imaging/libImaging/GifDecode.c
@@ -0,0 +1,297 @@
+/*
+ * The Python Imaging Library.
+ * $Id: GifDecode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * a fast, suspendable GIF decoder
+ *
+ * history:
+ * 95-09-03 fl Created
+ * 95-09-05 fl Fixed sign problem on 16-bit platforms
+ * 95-09-13 fl Added some storage shortcuts
+ * 96-03-28 fl Revised API, integrated with PIL
+ * 96-12-10 fl Added interlace support
+ * 96-12-16 fl Fixed premature termination bug introduced by last fix
+ * 97-01-05 fl Don't mess up on bogus configuration
+ * 97-01-17 fl Don't mess up on very small, interlaced files
+ * 99-02-07 fl Minor speedups
+ *
+ * Copyright (c) Secret Labs AB 1997-99.
+ * Copyright (c) Fredrik Lundh 1995-97.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+#include <stdio.h>
+#include <memory.h> /* memcpy() */
+
+#include "Gif.h"
+
+
+#define NEWLINE(state, context) {\
+ state->x = 0;\
+ state->y += context->step;\
+ while (state->y >= state->ysize)\
+ switch (context->interlace) {\
+ case 1:\
+ context->repeat = state->y = 4;\
+ context->interlace = 2;\
+ break;\
+ case 2:\
+ context->step = 4;\
+ context->repeat = state->y = 2;\
+ context->interlace = 3;\
+ break;\
+ case 3:\
+ context->step = 2;\
+ context->repeat = state->y = 1;\
+ context->interlace = 0;\
+ break;\
+ default:\
+ return -1;\
+ }\
+ if (state->y < state->ysize)\
+ out = im->image8[state->y + state->yoff] + state->xoff;\
+}
+
+
+int
+ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, int bytes)
+{
+ UINT8* p;
+ UINT8* out;
+ int c, i;
+ int thiscode;
+ GIFDECODERSTATE *context = (GIFDECODERSTATE*) state->context;
+
+ UINT8 *ptr = buffer;
+
+ if (!state->state) {
+
+ /* Initialise state */
+ if (context->bits < 0 || context->bits > 8) {
+ state->errcode = IMAGING_CODEC_CONFIG;
+ return -1;
+ }
+
+ /* Clear code */
+ context->clear = 1 << context->bits;
+
+ /* End code */
+ context->end = context->clear + 1;
+
+ /* Interlace */
+ if (context->interlace) {
+ context->interlace = 1;
+ context->step = context->repeat = 8;
+ } else
+ context->step = 1;
+
+ state->state = 1;
+ }
+
+ out = im->image8[state->y + state->yoff] + state->xoff + state->x;
+
+ for (;;) {
+
+ if (state->state == 1) {
+
+ /* First free entry in table */
+ context->next = context->clear + 2;
+
+ /* Initial code size */
+ context->codesize = context->bits + 1;
+ context->codemask = (1 << context->codesize) - 1;
+
+ /* Buffer pointer. We fill the buffer from right, which
+ allows us to return all of it in one operation. */
+ context->bufferindex = GIFBUFFER;
+
+ state->state = 2;
+ }
+
+ if (context->bufferindex < GIFBUFFER) {
+
+ /* Return whole buffer in one chunk */
+ i = GIFBUFFER - context->bufferindex;
+ p = &context->buffer[context->bufferindex];
+
+ context->bufferindex = GIFBUFFER;
+
+ } else {
+
+ /* Get current symbol */
+
+ while (context->bitcount < context->codesize) {
+
+ if (context->blocksize > 0) {
+
+ /* Read next byte */
+ c = *ptr++; bytes--;
+
+ context->blocksize--;
+
+ /* New bits are shifted in from from the left. */
+ context->bitbuffer |= (INT32) c << context->bitcount;
+ context->bitcount += 8;
+
+ } else {
+
+ /* New GIF block */
+
+ /* We don't start decoding unless we have a full block */
+ if (bytes < 1)
+ return ptr - buffer;
+ c = *ptr;
+ if (bytes < c+1)
+ return ptr - buffer;
+
+ context->blocksize = c;
+
+ ptr++; bytes--;
+
+ }
+ }
+
+ /* Extract current symbol from bit buffer. */
+ c = (int) context->bitbuffer & context->codemask;
+
+ /* Adjust buffer */
+ context->bitbuffer >>= context->codesize;
+ context->bitcount -= context->codesize;
+
+ /* If c is less than "clear", it's a data byte. Otherwise,
+ it's either clear/end or a code symbol which should be
+ expanded. */
+
+ if (c == context->clear) {
+ if (state->state != 2)
+ state->state = 1;
+ continue;
+ }
+
+ if (c == context->end)
+ break;
+
+ i = 1;
+ p = &context->lastdata;
+
+ if (state->state == 2) {
+
+ /* First valid symbol after clear; use as is */
+ if (c > context->clear) {
+ state->errcode = IMAGING_CODEC_BROKEN;
+ return -1;
+ }
+
+ context->lastdata = context->lastcode = c;
+ state->state = 3;
+
+ } else {
+
+ thiscode = c;
+
+ if (c > context->next) {
+ state->errcode = IMAGING_CODEC_BROKEN;
+ return -1;
+ }
+
+ if (c == context->next) {
+
+ /* c == next is allowed. not sure why. */
+
+ if (context->bufferindex <= 0) {
+ state->errcode = IMAGING_CODEC_BROKEN;
+ return -1;
+ }
+
+ context->buffer[--context->bufferindex] =
+ context->lastdata;
+
+ c = context->lastcode;
+
+ }
+
+ while (c >= context->clear) {
+
+ /* Copy data string to buffer (beginning from right) */
+
+ if (context->bufferindex <= 0 || c >= GIFTABLE) {
+ state->errcode = IMAGING_CODEC_BROKEN;
+ return -1;
+ }
+
+ context->buffer[--context->bufferindex] =
+ context->data[c];
+
+ c = context->link[c];
+ }
+
+ context->lastdata = c;
+
+ if (context->next < GIFTABLE) {
+
+ /* We'll only add this symbol if we have room
+ for it (take advise, Netscape!) */
+ context->data[context->next] = c;
+ context->link[context->next] = context->lastcode;
+
+ if (context->next == context->codemask &&
+ context->codesize < GIFBITS) {
+
+ /* Expand code size */
+ context->codesize++;
+ context->codemask = (1 << context->codesize) - 1;
+ }
+
+ context->next++;
+
+ }
+
+ context->lastcode = thiscode;
+
+ }
+ }
+
+ /* Copy the bytes into the image */
+ if (state->y >= state->ysize) {
+ state->errcode = IMAGING_CODEC_OVERRUN;
+ return -1;
+ }
+
+ /* To squeeze some extra pixels out of this loop, we test for
+ some common cases and handle them separately. */
+
+ /* FIXME: should we handle the transparency index in here??? */
+
+ if (i == 1) {
+ if (state->x < state->xsize-1) {
+ /* Single pixel, not at the end of the line. */
+ *out++ = p[0];
+ state->x++;
+ continue;
+ }
+ } else if (state->x + i <= state->xsize) {
+ /* This string fits into current line. */
+ memcpy(out, p, i);
+ out += i;
+ state->x += i;
+ if (state->x == state->xsize) {
+ NEWLINE(state, context);
+ }
+ continue;
+ }
+
+ /* No shortcut, copy pixel by pixel */
+ for (c = 0; c < i; c++) {
+ *out++ = p[c];
+ if (++state->x >= state->xsize) {
+ NEWLINE(state, context);
+ }
+ }
+ }
+
+ return ptr - buffer;
+}
diff --git a/Imaging/libImaging/GifEncode.c b/Imaging/libImaging/GifEncode.c
new file mode 100644
index 0000000..fd696c1
--- /dev/null
+++ b/Imaging/libImaging/GifEncode.c
@@ -0,0 +1,319 @@
+/*
+ * The Python Imaging Library.
+ * $Id: GifEncode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * encoder for uncompressed GIF data
+ *
+ * history:
+ * 97-01-05 fl created (writes uncompressed data)
+ * 97-08-27 fl fixed off-by-one error in buffer size test
+ * 98-07-09 fl added interlace write support
+ * 99-02-07 fl rewritten, now uses a run-length encoding strategy
+ * 99-02-08 fl improved run-length encoding for long runs
+ *
+ * Copyright (c) Secret Labs AB 1997-99.
+ * Copyright (c) Fredrik Lundh 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+#include "Imaging.h"
+
+#include "Gif.h"
+
+/* codes from 0 to 255 are literals */
+#define CLEAR_CODE 256
+#define EOF_CODE 257
+#define FIRST_CODE 258
+#define LAST_CODE 511
+
+enum { INIT, ENCODE, ENCODE_EOF, FLUSH, EXIT };
+
+/* to make things a little less complicated, we use a simple output
+ queue to hold completed blocks. the following inlined function
+ adds a byte to the current block. it allocates a new block if
+ necessary. */
+
+static inline int
+emit(GIFENCODERSTATE *context, int byte)
+{
+ /* write a byte to the output buffer */
+
+ if (!context->block || context->block->size == 255) {
+ GIFENCODERBLOCK* block;
+
+ /* no room in the current block (or no current block);
+ allocate a new one */
+
+ /* add current block to end of flush queue */
+ if (context->block) {
+ block = context->flush;
+ while (block && block->next)
+ block = block->next;
+ if (block)
+ block->next = context->block;
+ else
+ context->flush = context->block;
+ }
+
+ /* get a new block */
+ if (context->free) {
+ block = context->free;
+ context->free = NULL;
+ } else {
+ block = malloc(sizeof(GIFENCODERBLOCK));
+ if (!block)
+ return 0;
+ }
+
+ block->size = 0;
+ block->next = NULL;
+
+ context->block = block;
+
+ }
+
+ /* write new byte to block */
+ context->block->data[context->block->size++] = byte;
+
+ return 1;
+}
+
+/* write a code word to the current block. this is a macro to make
+ sure it's inlined on all platforms */
+
+#define EMIT(code) {\
+ context->bitbuffer |= ((INT32) (code)) << context->bitcount;\
+ context->bitcount += 9;\
+ while (context->bitcount >= 8) {\
+ if (!emit(context, (UINT8) context->bitbuffer)) {\
+ state->errcode = IMAGING_CODEC_MEMORY;\
+ return 0;\
+ }\
+ context->bitbuffer >>= 8;\
+ context->bitcount -= 8;\
+ }\
+}
+
+/* write a run. we use a combination of literals and combinations of
+ literals. this can give quite decent compression for images with
+ long stretches of identical pixels. but remember: if you want
+ really good compression, use another file format. */
+
+#define EMIT_RUN(label) {\
+label:\
+ while (context->count > 0) {\
+ int run = 2;\
+ EMIT(context->last);\
+ context->count--;\
+ if (state->count++ == LAST_CODE) {\
+ EMIT(CLEAR_CODE);\
+ state->count = FIRST_CODE;\
+ goto label;\
+ }\
+ while (context->count >= run) {\
+ EMIT(state->count - 1);\
+ context->count -= run;\
+ run++;\
+ if (state->count++ == LAST_CODE) {\
+ EMIT(CLEAR_CODE);\
+ state->count = FIRST_CODE;\
+ goto label;\
+ }\
+ }\
+ if (context->count > 1) {\
+ EMIT(state->count - 1 - (run - context->count));\
+ context->count = 0;\
+ if (state->count++ == LAST_CODE) {\
+ EMIT(CLEAR_CODE);\
+ state->count = FIRST_CODE;\
+ }\
+ break;\
+ }\
+ }\
+}
+
+int
+ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ UINT8* ptr;
+ int this;
+
+ GIFENCODERBLOCK* block;
+ GIFENCODERSTATE *context = (GIFENCODERSTATE*) state->context;
+
+ if (!state->state) {
+
+ /* place a clear code in the output buffer */
+ context->bitbuffer = CLEAR_CODE;
+ context->bitcount = 9;
+
+ state->count = FIRST_CODE;
+
+ if (context->interlace) {
+ context->interlace = 1;
+ context->step = 8;
+ } else
+ context->step = 1;
+
+ context->last = -1;
+
+ /* sanity check */
+ if (state->xsize <= 0 || state->ysize <= 0)
+ state->state = ENCODE_EOF;
+
+ }
+
+ ptr = buf;
+
+ for (;;)
+
+ switch (state->state) {
+
+ case INIT:
+ case ENCODE:
+
+ /* identify and store a run of pixels */
+
+ if (state->x == 0 || state->x >= state->xsize) {
+
+ if (!context->interlace && state->y >= state->ysize) {
+ state->state = ENCODE_EOF;
+ break;
+ }
+
+ if (context->flush) {
+ state->state = FLUSH;
+ break;
+ }
+
+ /* get another line of data */
+ state->shuffle(
+ state->buffer,
+ (UINT8*) im->image[state->y + state->yoff] +
+ state->xoff * im->pixelsize, state->xsize
+ );
+
+ state->x = 0;
+
+ if (state->state == INIT) {
+ /* preload the run-length buffer and get going */
+ context->last = state->buffer[0];
+ context->count = state->x = 1;
+ state->state = ENCODE;
+ }
+
+ /* step forward, according to the interlace settings */
+ state->y += context->step;
+ while (context->interlace && state->y >= state->ysize)
+ switch (context->interlace) {
+ case 1:
+ state->y = 4;
+ context->interlace = 2;
+ break;
+ case 2:
+ context->step = 4;
+ state->y = 2;
+ context->interlace = 3;
+ break;
+ case 3:
+ context->step = 2;
+ state->y = 1;
+ context->interlace = 0;
+ break;
+ default:
+ /* just make sure we don't loop forever */
+ context->interlace = 0;
+ }
+
+ }
+
+ this = state->buffer[state->x++];
+
+ if (this == context->last)
+ context->count++;
+ else {
+ EMIT_RUN(label1);
+ context->last = this;
+ context->count = 1;
+ }
+ break;
+
+
+ case ENCODE_EOF:
+
+ /* write the final run */
+ EMIT_RUN(label2);
+
+ /* write an end of image marker */
+ EMIT(EOF_CODE);
+
+ /* empty the bit buffer */
+ while (context->bitcount > 0) {
+ if (!emit(context, (UINT8) context->bitbuffer)) {
+ state->errcode = IMAGING_CODEC_MEMORY;
+ return 0;
+ }
+ context->bitbuffer >>= 8;
+ context->bitcount -= 8;
+ }
+
+ /* flush the last block, and exit */
+ if (context->block) {
+ GIFENCODERBLOCK* block;
+ block = context->flush;
+ while (block && block->next)
+ block = block->next;
+ if (block)
+ block->next = context->block;
+ else
+ context->flush = context->block;
+ context->block = NULL;
+ }
+
+ state->state = EXIT;
+
+ /* fall through... */
+
+ case EXIT:
+ case FLUSH:
+
+ while (context->flush) {
+
+ /* get a block from the flush queue */
+ block = context->flush;
+
+ if (block->size > 0) {
+
+ /* make sure it fits into the output buffer */
+ if (bytes < block->size+1)
+ return ptr - buf;
+
+ ptr[0] = block->size;
+ memcpy(ptr+1, block->data, block->size);
+
+ ptr += block->size+1;
+ bytes -= block->size+1;
+
+ }
+
+ context->flush = block->next;
+
+ if (context->free)
+ free(context->free);
+ context->free = block;
+
+ }
+
+ if (state->state == EXIT) {
+ /* this was the last block! */
+ if (context->free)
+ free(context->free);
+ state->errcode = IMAGING_CODEC_END;
+ return ptr - buf;
+ }
+
+ state->state = ENCODE;
+ break;
+ }
+}
diff --git a/Imaging/libImaging/HexDecode.c b/Imaging/libImaging/HexDecode.c
new file mode 100644
index 0000000..dddbe00
--- /dev/null
+++ b/Imaging/libImaging/HexDecode.c
@@ -0,0 +1,67 @@
+/*
+ * The Python Imaging Library.
+ * $Id: HexDecode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * decoder for hex encoded image data
+ *
+ * history:
+ * 96-05-16 fl Created
+ *
+ * Copyright (c) Fredrik Lundh 1996.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+#define HEX(v) ((v >= '0' && v <= '9') ? v - '0' :\
+ (v >= 'a' && v <= 'f') ? v - 'a' + 10 :\
+ (v >= 'A' && v <= 'F') ? v - 'A' + 10 : -1)
+
+int
+ImagingHexDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ UINT8* ptr;
+ int a, b;
+
+ ptr = buf;
+
+ for (;;) {
+
+ if (bytes < 2)
+ return ptr - buf;
+
+ a = HEX(ptr[0]);
+ b = HEX(ptr[1]);
+
+ if (a < 0 || b < 0) {
+
+ ptr++;
+ bytes--;
+
+ } else {
+
+ ptr += 2;
+ bytes -= 2;
+
+ state->buffer[state->x] = (a<<4) + b;
+
+ if (++state->x >= state->bytes) {
+
+ /* Got a full line, unpack it */
+ state->shuffle((UINT8*) im->image[state->y], state->buffer,
+ state->xsize);
+
+ state->x = 0;
+
+ if (++state->y >= state->ysize) {
+ /* End of file (errcode = 0) */
+ return -1;
+ }
+ }
+
+ }
+ }
+}
diff --git a/Imaging/libImaging/Histo.c b/Imaging/libImaging/Histo.c
new file mode 100644
index 0000000..b69b1db
--- /dev/null
+++ b/Imaging/libImaging/Histo.c
@@ -0,0 +1,169 @@
+/*
+ * The Python Imaging Library
+ * $Id: Histo.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * histogram support
+ *
+ * history:
+ * 1995-06-15 fl Created.
+ * 1996-04-05 fl Fixed histogram for multiband images.
+ * 1997-02-23 fl Added mask support
+ * 1998-07-01 fl Added basic 32-bit float/integer support
+ *
+ * Copyright (c) 1997-2003 by Secret Labs AB.
+ * Copyright (c) 1995-2003 by Fredrik Lundh.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+/* HISTOGRAM */
+/* --------------------------------------------------------------------
+ * Take a histogram of an image. Returns a histogram object containing
+ * 256 slots per band in the input image.
+ */
+
+void
+ImagingHistogramDelete(ImagingHistogram h)
+{
+ if (h->histogram)
+ free(h->histogram);
+ free(h);
+}
+
+ImagingHistogram
+ImagingHistogramNew(Imaging im)
+{
+ ImagingHistogram h;
+
+ /* Create histogram descriptor */
+ h = calloc(1, sizeof(struct ImagingHistogramInstance));
+ strcpy(h->mode, im->mode);
+ h->bands = im->bands;
+ h->histogram = calloc(im->pixelsize, 256 * sizeof(long));
+
+ return h;
+}
+
+ImagingHistogram
+ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax)
+{
+ ImagingSectionCookie cookie;
+ int x, y, i;
+ ImagingHistogram h;
+ INT32 imin, imax;
+ FLOAT32 fmin, fmax, scale;
+
+ if (!im)
+ return ImagingError_ModeError();
+
+ if (imMask) {
+ /* Validate mask */
+ if (im->xsize != imMask->xsize || im->ysize != imMask->ysize)
+ return ImagingError_Mismatch();
+ if (strcmp(imMask->mode, "1") != 0 && strcmp(imMask->mode, "L") != 0)
+ return ImagingError_ValueError("bad transparency mask");
+ }
+
+ h = ImagingHistogramNew(im);
+
+ if (imMask) {
+ /* mask */
+ if (im->image8) {
+ ImagingSectionEnter(&cookie);
+ for (y = 0; y < im->ysize; y++)
+ for (x = 0; x < im->xsize; x++)
+ if (imMask->image8[y][x] != 0)
+ h->histogram[im->image8[y][x]]++;
+ ImagingSectionLeave(&cookie);
+ } else { /* yes, we need the braces. C isn't Python! */
+ if (im->type != IMAGING_TYPE_UINT8)
+ return ImagingError_ModeError();
+ ImagingSectionEnter(&cookie);
+ for (y = 0; y < im->ysize; y++) {
+ UINT8* in = (UINT8*) im->image32[y];
+ for (x = 0; x < im->xsize; x++)
+ if (imMask->image8[y][x] != 0) {
+ h->histogram[(*in++)]++;
+ h->histogram[(*in++)+256]++;
+ h->histogram[(*in++)+512]++;
+ h->histogram[(*in++)+768]++;
+ } else
+ in += 4;
+ }
+ ImagingSectionLeave(&cookie);
+ }
+ } else {
+ /* mask not given; process pixels in image */
+ if (im->image8) {
+ ImagingSectionEnter(&cookie);
+ for (y = 0; y < im->ysize; y++)
+ for (x = 0; x < im->xsize; x++)
+ h->histogram[im->image8[y][x]]++;
+ ImagingSectionLeave(&cookie);
+ } else {
+ switch (im->type) {
+ case IMAGING_TYPE_UINT8:
+ ImagingSectionEnter(&cookie);
+ for (y = 0; y < im->ysize; y++) {
+ UINT8* in = (UINT8*) im->image[y];
+ for (x = 0; x < im->xsize; x++) {
+ h->histogram[(*in++)]++;
+ h->histogram[(*in++)+256]++;
+ h->histogram[(*in++)+512]++;
+ h->histogram[(*in++)+768]++;
+ }
+ }
+ ImagingSectionLeave(&cookie);
+ break;
+ case IMAGING_TYPE_INT32:
+ if (!minmax)
+ return ImagingError_ValueError("min/max not given");
+ if (!im->xsize || !im->ysize)
+ break;
+ imin = ((INT32*) minmax)[0];
+ imax = ((INT32*) minmax)[1];
+ if (imin >= imax)
+ break;
+ ImagingSectionEnter(&cookie);
+ scale = 255.0F / (imax - imin);
+ for (y = 0; y < im->ysize; y++) {
+ INT32* in = im->image32[y];
+ for (x = 0; x < im->xsize; x++) {
+ i = (int) (((*in++)-imin)*scale);
+ if (i >= 0 && i < 256)
+ h->histogram[i]++;
+ }
+ }
+ ImagingSectionLeave(&cookie);
+ break;
+ case IMAGING_TYPE_FLOAT32:
+ if (!minmax)
+ return ImagingError_ValueError("min/max not given");
+ if (!im->xsize || !im->ysize)
+ break;
+ fmin = ((FLOAT32*) minmax)[0];
+ fmax = ((FLOAT32*) minmax)[1];
+ if (fmin >= fmax)
+ break;
+ ImagingSectionEnter(&cookie);
+ scale = 255.0F / (fmax - fmin);
+ for (y = 0; y < im->ysize; y++) {
+ FLOAT32* in = (FLOAT32*) im->image32[y];
+ for (x = 0; x < im->xsize; x++) {
+ i = (int) (((*in++)-fmin)*scale);
+ if (i >= 0 && i < 256)
+ h->histogram[i]++;
+ }
+ }
+ ImagingSectionLeave(&cookie);
+ break;
+ }
+ }
+ }
+
+ return h;
+}
diff --git a/Imaging/libImaging/ImDib.h b/Imaging/libImaging/ImDib.h
new file mode 100644
index 0000000..129cb22
--- /dev/null
+++ b/Imaging/libImaging/ImDib.h
@@ -0,0 +1,64 @@
+/*
+ * The Python Imaging Library
+ * $Id: ImDib.h 2319 2005-03-11 16:41:26Z fredrik $
+ *
+ * Windows DIB specifics
+ *
+ * Copyright (c) Secret Labs AB 1997-98.
+ * Copyright (c) Fredrik Lundh 1996.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+#ifdef WIN32
+
+#if (defined(_MSC_VER) && _MSC_VER >= 1200) || (defined __GNUC__)
+/* already defined in basetsd.h */
+#undef INT32
+#undef INT64
+#undef UINT32
+#endif
+
+#include <windows.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct ImagingDIBInstance {
+ /* Windows interface */
+ HDC dc;
+ HBITMAP bitmap;
+ HGDIOBJ old_bitmap;
+ BITMAPINFO *info;
+ UINT8 *bits;
+ HPALETTE palette;
+ /* Used by cut and paste */
+ char mode[4];
+ int xsize, ysize;
+ int pixelsize;
+ int linesize;
+ ImagingShuffler pack;
+ ImagingShuffler unpack;
+};
+
+typedef struct ImagingDIBInstance* ImagingDIB;
+
+extern char* ImagingGetModeDIB(int size_out[2]);
+
+extern ImagingDIB ImagingNewDIB(const char *mode, int xsize, int ysize);
+
+extern void ImagingDeleteDIB(ImagingDIB im);
+
+extern void ImagingDrawDIB(ImagingDIB dib, int dc, int dst[4], int src[4]);
+extern void ImagingExposeDIB(ImagingDIB dib, int dc);
+
+extern int ImagingQueryPaletteDIB(ImagingDIB dib, int dc);
+
+extern void ImagingPasteDIB(ImagingDIB dib, Imaging im, int xy[4]);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/Imaging/libImaging/ImPlatform.h b/Imaging/libImaging/ImPlatform.h
new file mode 100644
index 0000000..c3132d9
--- /dev/null
+++ b/Imaging/libImaging/ImPlatform.h
@@ -0,0 +1,72 @@
+/*
+ * The Python Imaging Library
+ * $Id: ImPlatform.h 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * platform declarations for the imaging core library
+ *
+ * Copyright (c) Fredrik Lundh 1995-2003.
+ */
+
+#include "Python.h"
+
+/* Check that we have an ANSI compliant compiler */
+#ifndef HAVE_PROTOTYPES
+#error Sorry, this library requires support for ANSI prototypes.
+#endif
+#ifndef STDC_HEADERS
+#error Sorry, this library requires ANSI header files.
+#endif
+
+#if defined(_MSC_VER)
+#ifndef WIN32
+#define WIN32
+#endif
+/* VC++ 4.0 is a bit annoying when it comes to precision issues (like
+ claiming that "float a = 0.0;" would lead to loss of precision). I
+ don't like to see warnings from my code, but since I still want to
+ keep it readable, I simply switch off a few warnings instead of adding
+ the tons of casts that VC++ seem to require. This code is compiled
+ with numerous other compilers as well, so any real errors are likely
+ to be catched anyway. */
+#pragma warning(disable: 4244) /* conversion from 'float' to 'int' */
+#endif
+
+#if defined(_MSC_VER)
+#define inline __inline
+#elif !defined(USE_INLINE)
+#define inline
+#endif
+
+#if SIZEOF_SHORT == 2
+#define INT16 short
+#elif SIZEOF_INT == 2
+#define INT16 int
+#else
+#define INT16 short /* most things works just fine anyway... */
+#endif
+
+#if SIZEOF_SHORT == 4
+#define INT32 short
+#elif SIZEOF_INT == 4
+#define INT32 int
+#elif SIZEOF_LONG == 4
+#define INT32 long
+#else
+#error Cannot find required 32-bit integer type
+#endif
+
+#if SIZEOF_LONG == 8
+#define INT64 long
+#elif SIZEOF_LONG_LONG == 8
+#define INT64 long
+#endif
+
+/* assume IEEE; tweak if necessary (patches are welcome) */
+#define FLOAT32 float
+#define FLOAT64 double
+
+#define INT8 signed char
+#define UINT8 unsigned char
+
+#define UINT16 unsigned INT16
+#define UINT32 unsigned INT32
diff --git a/Imaging/libImaging/Imaging.h b/Imaging/libImaging/Imaging.h
new file mode 100644
index 0000000..24b97eb
--- /dev/null
+++ b/Imaging/libImaging/Imaging.h
@@ -0,0 +1,495 @@
+/*
+ * The Python Imaging Library
+ * $Id: Imaging.h 2542 2005-10-02 21:37:20Z Fredrik $
+ *
+ * declarations for the imaging core library
+ *
+ * Copyright (c) 1997-2005 by Secret Labs AB
+ * Copyright (c) 1995-2005 by Fredrik Lundh
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "ImPlatform.h"
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#ifndef M_PI
+#define M_PI 3.14159265359
+#endif
+
+
+/* -------------------------------------------------------------------- */
+
+/*
+ * Image data organization:
+ *
+ * mode bytes byte order
+ * -------------------------------
+ * 1 1 1
+ * L 1 L
+ * P 1 P
+ * I 4 I (32-bit integer, native byte order)
+ * F 4 F (32-bit IEEE float, native byte order)
+ * RGB 4 R, G, B, -
+ * RGBA 4 R, G, B, A
+ * CMYK 4 C, M, Y, K
+ * YCbCr 4 Y, Cb, Cr, -
+ *
+ * experimental modes (incomplete):
+ * LA 4 L, -, -, A
+ * PA 4 P, -, -, A
+ * I;16 2 I (16-bit integer, native byte order)
+ *
+ * "P" is an 8-bit palette mode, which should be mapped through the
+ * palette member to get an output image. Check palette->mode to
+ * find the corresponding "real" mode.
+ *
+ * For information on how to access Imaging objects from your own C
+ * extensions, see http://www.effbot.org/zone/pil-extending.htm
+ */
+
+/* Handles */
+
+typedef struct ImagingMemoryInstance* Imaging;
+typedef struct ImagingAccessInstance* ImagingAccess;
+typedef struct ImagingHistogramInstance* ImagingHistogram;
+typedef struct ImagingOutlineInstance* ImagingOutline;
+typedef struct ImagingPaletteInstance* ImagingPalette;
+
+/* handle magics (used with PyCObject). */
+#define IMAGING_MAGIC "PIL Imaging"
+#define IMAGING_ACCESS_MAGIC "PIL ImagingAccess"
+
+/* pixel types */
+#define IMAGING_TYPE_UINT8 0
+#define IMAGING_TYPE_INT32 1
+#define IMAGING_TYPE_FLOAT32 2
+#define IMAGING_TYPE_SPECIAL 3 /* check mode for details */
+
+struct ImagingMemoryInstance {
+
+ /* Format */
+ char mode[4+1]; /* Band names ("1", "L", "P", "RGB", "RGBA", "CMYK") */
+ int type; /* Data type (IMAGING_TYPE_*) */
+ int depth; /* Depth (ignored in this version) */
+ int bands; /* Number of bands (1, 2, 3, or 4) */
+ int xsize; /* Image dimension. */
+ int ysize;
+
+ /* Colour palette (for "P" images only) */
+ ImagingPalette palette;
+
+ /* Data pointers */
+ UINT8 **image8; /* Set for 8-bit images (pixelsize=1). */
+ INT32 **image32; /* Set for 32-bit images (pixelsize=4). */
+
+ /* Internals */
+ char **image; /* Actual raster data. */
+ char *block; /* Set if data is allocated in a single block. */
+
+ int pixelsize; /* Size of a pixel, in bytes (1, 2 or 4) */
+ int linesize; /* Size of a line, in bytes (xsize * pixelsize) */
+
+ /* Virtual methods */
+ void (*destroy)(Imaging im);
+
+};
+
+
+#define IMAGING_PIXEL_1(im,x,y) ((im)->image8[(y)][(x)])
+#define IMAGING_PIXEL_L(im,x,y) ((im)->image8[(y)][(x)])
+#define IMAGING_PIXEL_LA(im,x,y) ((im)->image[(y)][(x)*4])
+#define IMAGING_PIXEL_P(im,x,y) ((im)->image8[(y)][(x)])
+#define IMAGING_PIXEL_PA(im,x,y) ((im)->image[(y)][(x)*4])
+#define IMAGING_PIXEL_I(im,x,y) ((im)->image32[(y)][(x)])
+#define IMAGING_PIXEL_F(im,x,y) (((FLOAT32*)(im)->image32[y])[x])
+#define IMAGING_PIXEL_RGB(im,x,y) ((im)->image[(y)][(x)*4])
+#define IMAGING_PIXEL_RGBA(im,x,y) ((im)->image[(y)][(x)*4])
+#define IMAGING_PIXEL_CMYK(im,x,y) ((im)->image[(y)][(x)*4])
+#define IMAGING_PIXEL_YCbCr(im,x,y) ((im)->image[(y)][(x)*4])
+
+#define IMAGING_PIXEL_UINT8(im,x,y) ((im)->image8[(y)][(x)])
+#define IMAGING_PIXEL_INT32(im,x,y) ((im)->image32[(y)][(x)])
+#define IMAGING_PIXEL_FLOAT32(im,x,y) (((FLOAT32*)(im)->image32[y])[x])
+
+#define IMAGING_ACCESS_HEAD\
+ int (*getline)(ImagingAccess access, char *buffer, int y);\
+ void (*destroy)(ImagingAccess access)
+
+struct ImagingAccessInstance {
+ IMAGING_ACCESS_HEAD;
+
+ /* Data members */
+ Imaging im;
+
+};
+
+
+struct ImagingHistogramInstance {
+
+ /* Format */
+ char mode[4+1]; /* Band names (of corresponding source image) */
+ int bands; /* Number of bands (1, 3, or 4) */
+
+ /* Data */
+ long *histogram; /* Histogram (bands*256 longs) */
+
+};
+
+
+struct ImagingPaletteInstance {
+
+ /* Format */
+ char mode[4+1]; /* Band names */
+
+ /* Data */
+ UINT8 palette[1024];/* Palette data (same format as image data) */
+
+ INT16* cache; /* Palette cache (used for predefined palettes) */
+ int keep_cache; /* This palette will be reused; keep cache */
+
+};
+
+
+/* Objects */
+/* ------- */
+
+extern int ImagingNewCount;
+
+extern Imaging ImagingNew(const char* mode, int xsize, int ysize);
+extern Imaging ImagingNew2(const char* mode, Imaging imOut, Imaging imIn);
+extern void ImagingDelete(Imaging im);
+
+extern Imaging ImagingNewBlock(const char* mode, int xsize, int ysize);
+extern Imaging ImagingNewArray(const char* mode, int xsize, int ysize);
+extern Imaging ImagingNewMap(const char* filename, int readonly,
+ const char* mode, int xsize, int ysize);
+
+extern Imaging ImagingNewPrologue(const char *mode,
+ unsigned xsize, unsigned ysize);
+extern Imaging ImagingNewPrologueSubtype(const char *mode,
+ unsigned xsize, unsigned ysize,
+ int structure_size);
+extern Imaging ImagingNewEpilogue(Imaging im);
+
+extern void ImagingCopyInfo(Imaging destination, Imaging source);
+
+extern void ImagingHistogramDelete(ImagingHistogram histogram);
+
+extern ImagingAccess ImagingAccessNew(Imaging im);
+extern void ImagingAccessDelete(ImagingAccess access);
+
+extern ImagingPalette ImagingPaletteNew(const char *mode);
+extern ImagingPalette ImagingPaletteNewBrowser(void);
+extern ImagingPalette ImagingPaletteDuplicate(ImagingPalette palette);
+extern void ImagingPaletteDelete(ImagingPalette palette);
+
+extern int ImagingPaletteCachePrepare(ImagingPalette palette);
+extern void ImagingPaletteCacheUpdate(ImagingPalette palette,
+ int r, int g, int b);
+extern void ImagingPaletteCacheDelete(ImagingPalette palette);
+
+#define ImagingPaletteCache(p, r, g, b)\
+ p->cache[(r>>2) + (g>>2)*64 + (b>>2)*64*64]
+
+extern Imaging ImagingQuantize(Imaging im, int colours, int mode, int kmeans);
+
+/* Threading */
+/* --------- */
+
+typedef void* ImagingSectionCookie;
+
+extern void ImagingSectionEnter(ImagingSectionCookie* cookie);
+extern void ImagingSectionLeave(ImagingSectionCookie* cookie);
+
+/* Exceptions */
+/* ---------- */
+
+extern void* ImagingError_IOError(void);
+extern void* ImagingError_MemoryError(void);
+extern void* ImagingError_ModeError(void); /* maps to ValueError by default */
+extern void* ImagingError_Mismatch(void); /* maps to ValueError by default */
+extern void* ImagingError_ValueError(const char* message);
+
+/* Transform callbacks */
+/* ------------------- */
+
+/* standard transforms */
+#define IMAGING_TRANSFORM_AFFINE 0
+#define IMAGING_TRANSFORM_PERSPECTIVE 2
+#define IMAGING_TRANSFORM_QUAD 3
+
+
+/* standard filters */
+#define IMAGING_TRANSFORM_NEAREST 0
+#define IMAGING_TRANSFORM_ANTIALIAS 1
+#define IMAGING_TRANSFORM_BILINEAR 2
+#define IMAGING_TRANSFORM_BICUBIC 3
+
+typedef int (*ImagingTransformMap)(double* X, double* Y,
+ int x, int y, void* data);
+typedef int (*ImagingTransformFilter)(void* out, Imaging im,
+ double x, double y,
+ void* data);
+
+/* Image Manipulation Methods */
+/* -------------------------- */
+
+extern Imaging ImagingBlend(Imaging imIn1, Imaging imIn2, float alpha);
+extern Imaging ImagingCopy(Imaging im);
+extern Imaging ImagingConvert(
+ Imaging im, const char* mode, ImagingPalette palette, int dither);
+extern Imaging ImagingConvertMatrix(Imaging im, const char *mode, float m[]);
+extern Imaging ImagingCrop(Imaging im, int x0, int y0, int x1, int y1);
+extern Imaging ImagingExpand(Imaging im, int x, int y, int mode);
+extern Imaging ImagingFill(Imaging im, const void* ink);
+extern int ImagingFill2(
+ Imaging into, const void* ink, Imaging mask,
+ int x0, int y0, int x1, int y1);
+extern Imaging ImagingFillBand(Imaging im, int band, int color);
+extern Imaging ImagingFillLinearGradient(const char* mode);
+extern Imaging ImagingFillRadialGradient(const char* mode);
+extern Imaging ImagingFilter(
+ Imaging im, int xsize, int ysize, const FLOAT32* kernel,
+ FLOAT32 offset, FLOAT32 divisor);
+extern Imaging ImagingFlipLeftRight(Imaging imOut, Imaging imIn);
+extern Imaging ImagingFlipTopBottom(Imaging imOut, Imaging imIn);
+extern Imaging ImagingGetBand(Imaging im, int band);
+extern int ImagingGetBBox(Imaging im, int bbox[4]);
+typedef struct { int x, y; INT32 count; INT32 pixel; } ImagingColorItem;
+extern ImagingColorItem* ImagingGetColors(Imaging im, int maxcolors,
+ int *colors);
+extern int ImagingGetExtrema(Imaging im, void *extrema);
+extern int ImagingGetProjection(Imaging im, UINT8* xproj, UINT8* yproj);
+extern ImagingHistogram ImagingGetHistogram(
+ Imaging im, Imaging mask, void *extrema);
+extern Imaging ImagingModeFilter(Imaging im, int size);
+extern Imaging ImagingNegative(Imaging im);
+extern Imaging ImagingOffset(Imaging im, int xoffset, int yoffset);
+extern int ImagingPaste(
+ Imaging into, Imaging im, Imaging mask,
+ int x0, int y0, int x1, int y1);
+extern Imaging ImagingPoint(
+ Imaging im, const char* tablemode, const void* table);
+extern Imaging ImagingPointTransform(
+ Imaging imIn, double scale, double offset);
+extern Imaging ImagingPutBand(Imaging im, Imaging imIn, int band);
+extern Imaging ImagingRankFilter(Imaging im, int size, int rank);
+extern Imaging ImagingResize(Imaging imOut, Imaging imIn, int filter);
+extern Imaging ImagingRotate(
+ Imaging imOut, Imaging imIn, double theta, int filter);
+extern Imaging ImagingRotate90(Imaging imOut, Imaging imIn);
+extern Imaging ImagingRotate180(Imaging imOut, Imaging imIn);
+extern Imaging ImagingRotate270(Imaging imOut, Imaging imIn);
+extern Imaging ImagingStretch(Imaging imOut, Imaging imIn, int filter);
+extern Imaging ImagingTransformPerspective(
+ Imaging imOut, Imaging imIn, int x0, int y0, int x1, int y1,
+ double a[8], int filter, int fill);
+extern Imaging ImagingTransformAffine(
+ Imaging imOut, Imaging imIn, int x0, int y0, int x1, int y1,
+ double a[6], int filter, int fill);
+extern Imaging ImagingTransformQuad(
+ Imaging imOut, Imaging imIn, int x0, int y0, int x1, int y1,
+ double a[8], int filter, int fill);
+extern Imaging ImagingTransform(
+ Imaging imOut, Imaging imIn, int x0, int y0, int x1, int y1,
+ ImagingTransformMap transform, void* transform_data,
+ ImagingTransformFilter filter, void* filter_data,
+ int fill);
+extern Imaging ImagingCopy2(Imaging imOut, Imaging imIn);
+extern Imaging ImagingConvert2(Imaging imOut, Imaging imIn);
+
+/* Channel operations */
+/* any mode, except "F" */
+extern Imaging ImagingChopLighter(Imaging imIn1, Imaging imIn2);
+extern Imaging ImagingChopDarker(Imaging imIn1, Imaging imIn2);
+extern Imaging ImagingChopDifference(Imaging imIn1, Imaging imIn2);
+extern Imaging ImagingChopMultiply(Imaging imIn1, Imaging imIn2);
+extern Imaging ImagingChopScreen(Imaging imIn1, Imaging imIn2);
+extern Imaging ImagingChopAdd(
+ Imaging imIn1, Imaging imIn2, float scale, int offset);
+extern Imaging ImagingChopSubtract(
+ Imaging imIn1, Imaging imIn2, float scale, int offset);
+extern Imaging ImagingChopAddModulo(Imaging imIn1, Imaging imIn2);
+extern Imaging ImagingChopSubtractModulo(Imaging imIn1, Imaging imIn2);
+
+/* "1" images only */
+extern Imaging ImagingChopAnd(Imaging imIn1, Imaging imIn2);
+extern Imaging ImagingChopOr(Imaging imIn1, Imaging imIn2);
+extern Imaging ImagingChopXor(Imaging imIn1, Imaging imIn2);
+
+/* Image measurement */
+extern void ImagingCrack(Imaging im, int x0, int y0);
+
+/* Graphics */
+struct ImagingAffineMatrixInstance {
+ float a[9];
+};
+
+typedef struct ImagingAffineMatrixInstance *ImagingAffineMatrix;
+
+extern int ImagingDrawArc(Imaging im, int x0, int y0, int x1, int y1,
+ int start, int end, const void* ink, int op);
+extern int ImagingDrawBitmap(Imaging im, int x0, int y0, Imaging bitmap,
+ const void* ink, int op);
+extern int ImagingDrawChord(Imaging im, int x0, int y0, int x1, int y1,
+ int start, int end, const void* ink, int fill,
+ int op);
+extern int ImagingDrawEllipse(Imaging im, int x0, int y0, int x1, int y1,
+ const void* ink, int fill, int op);
+extern int ImagingDrawLine(Imaging im, int x0, int y0, int x1, int y1,
+ const void* ink, int op);
+extern int ImagingDrawWideLine(Imaging im, int x0, int y0, int x1, int y1,
+ const void* ink, int width, int op);
+extern int ImagingDrawPieslice(Imaging im, int x0, int y0, int x1, int y1,
+ int start, int end, const void* ink, int fill,
+ int op);
+extern int ImagingDrawPoint(Imaging im, int x, int y, const void* ink, int op);
+extern int ImagingDrawPolygon(Imaging im, int points, int *xy,
+ const void* ink, int fill, int op);
+extern int ImagingDrawRectangle(Imaging im, int x0, int y0, int x1, int y1,
+ const void* ink, int fill, int op);
+
+/* Level 2 graphics (WORK IN PROGRESS) */
+extern ImagingOutline ImagingOutlineNew(void);
+extern void ImagingOutlineDelete(ImagingOutline outline);
+
+extern int ImagingDrawOutline(Imaging im, ImagingOutline outline,
+ const void* ink, int fill, int op);
+
+extern int ImagingOutlineMove(ImagingOutline outline, float x, float y);
+extern int ImagingOutlineLine(ImagingOutline outline, float x, float y);
+extern int ImagingOutlineCurve(ImagingOutline outline, float x1, float y1,
+ float x2, float y2, float x3, float y3);
+extern int ImagingOutlineTransform(ImagingOutline outline, double a[6]);
+
+extern int ImagingOutlineClose(ImagingOutline outline);
+
+/* Special effects */
+extern Imaging ImagingEffectSpread(Imaging imIn, int distance);
+extern Imaging ImagingEffectNoise(int xsize, int ysize, float sigma);
+extern Imaging ImagingEffectMandelbrot(int xsize, int ysize,
+ double extent[4], int quality);
+
+/* Obsolete */
+extern int ImagingToString(Imaging im, int orientation, char *buffer);
+extern int ImagingFromString(Imaging im, int orientation, char *buffer);
+
+
+/* File I/O */
+/* -------- */
+
+/* Built-in drivers */
+extern Imaging ImagingOpenPPM(const char* filename);
+extern int ImagingSavePPM(Imaging im, const char* filename);
+
+/* Utility functions */
+extern UINT32 ImagingCRC32(UINT32 crc, UINT8* buffer, int bytes);
+
+/* Codecs */
+typedef struct ImagingCodecStateInstance *ImagingCodecState;
+typedef int (*ImagingCodec)(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+
+extern int ImagingBitDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingEpsEncode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingFliDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingGifDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingGifEncode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingHexDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+#ifdef HAVE_LIBJPEG
+extern int ImagingJpegDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingJpegEncode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+#endif
+extern int ImagingLzwDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+#ifdef HAVE_LIBMPEG
+extern int ImagingMpegDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+#endif
+extern int ImagingMspDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingPackbitsDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingPcdDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingPcxDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingPcxEncode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingRawDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingRawEncode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingSunRleDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingTgaRleDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingXbmDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingXbmEncode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+#ifdef HAVE_LIBZ
+extern int ImagingZipDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingZipEncode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+#endif
+
+typedef void (*ImagingShuffler)(UINT8* out, const UINT8* in, int pixels);
+
+/* Public shufflers */
+extern void ImagingPackRGB(UINT8* out, const UINT8* in, int pixels);
+extern void ImagingPackBGR(UINT8* out, const UINT8* in, int pixels);
+extern void ImagingUnpackRGB(UINT8* out, const UINT8* in, int pixels);
+extern void ImagingUnpackBGR(UINT8* out, const UINT8* in, int pixels);
+extern void ImagingUnpackYCC(UINT8* out, const UINT8* in, int pixels);
+extern void ImagingUnpackYCCA(UINT8* out, const UINT8* in, int pixels);
+extern void ImagingUnpackYCbCr(UINT8* out, const UINT8* in, int pixels);
+
+extern void ImagingConvertRGB2YCbCr(UINT8* out, const UINT8* in, int pixels);
+extern void ImagingConvertYCbCr2RGB(UINT8* out, const UINT8* in, int pixels);
+
+extern ImagingShuffler ImagingFindUnpacker(const char* mode,
+ const char* rawmode, int* bits_out);
+extern ImagingShuffler ImagingFindPacker(const char* mode,
+ const char* rawmode, int* bits_out);
+
+struct ImagingCodecStateInstance {
+ int count;
+ int state;
+ int errcode;
+ int x, y;
+ int ystep;
+ int xsize, ysize, xoff, yoff;
+ ImagingShuffler shuffle;
+ int bits, bytes;
+ UINT8 *buffer;
+ void *context;
+};
+
+/* Errcodes */
+#define IMAGING_CODEC_END 1
+#define IMAGING_CODEC_OVERRUN -1
+#define IMAGING_CODEC_BROKEN -2
+#define IMAGING_CODEC_UNKNOWN -3
+#define IMAGING_CODEC_CONFIG -8
+#define IMAGING_CODEC_MEMORY -9
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/Imaging/libImaging/Jpeg.h b/Imaging/libImaging/Jpeg.h
new file mode 100644
index 0000000..45e0aec
--- /dev/null
+++ b/Imaging/libImaging/Jpeg.h
@@ -0,0 +1,96 @@
+/*
+ * The Python Imaging Library.
+ * $Id: Jpeg.h 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * declarations for the IJG JPEG codec interface.
+ *
+ * Copyright (c) 1995-2001 by Secret Labs AB
+ * Copyright (c) 1995-1996 by Fredrik Lundh
+ */
+
+#include "jpeglib.h"
+
+#include <setjmp.h>
+
+
+typedef struct {
+ struct jpeg_error_mgr pub; /* "public" fields */
+ jmp_buf setjmp_buffer; /* for return to caller */
+} JPEGERROR;
+
+
+/* -------------------------------------------------------------------- */
+/* Decoder */
+
+typedef struct {
+ struct jpeg_source_mgr pub;
+ int skip;
+} JPEGSOURCE;
+
+typedef struct {
+
+ /* CONFIGURATION */
+
+ /* Jpeg file mode (empty if not known) */
+ char jpegmode[8+1];
+
+ /* Converter output mode (input to the shuffler). If empty,
+ convert conversions are disabled */
+ char rawmode[8+1];
+
+ /* If set, trade quality for speed */
+ int draft;
+
+ /* Scale factor (1, 2, 4, 8) */
+ int scale;
+
+ /* PRIVATE CONTEXT (set by decoder) */
+
+ struct jpeg_decompress_struct cinfo;
+
+ JPEGERROR error;
+
+ JPEGSOURCE source;
+
+} JPEGSTATE;
+
+
+/* -------------------------------------------------------------------- */
+/* Encoder */
+
+typedef struct {
+ struct jpeg_destination_mgr pub;
+ /* might add something some other day */
+} JPEGDESTINATION;
+
+typedef struct {
+
+ /* CONFIGURATION */
+
+ /* Quality (1-100, 0 means default) */
+ int quality;
+
+ /* Progressive mode */
+ int progressive;
+
+ /* Smoothing factor (1-100, 0 means none) */
+ int smooth;
+
+ /* Optimize Huffman tables (slow) */
+ int optimize;
+
+ /* Stream type (0=full, 1=tables only, 2=image only) */
+ int streamtype;
+
+ /* DPI setting (0=square pixels, otherwide DPI) */
+ int xdpi, ydpi;
+
+ /* PRIVATE CONTEXT (set by encoder) */
+
+ struct jpeg_compress_struct cinfo;
+
+ JPEGERROR error;
+
+ JPEGDESTINATION destination;
+
+} JPEGENCODERSTATE;
diff --git a/Imaging/libImaging/JpegDecode.c b/Imaging/libImaging/JpegDecode.c
new file mode 100644
index 0000000..0e61aef
--- /dev/null
+++ b/Imaging/libImaging/JpegDecode.c
@@ -0,0 +1,266 @@
+/*
+ * The Python Imaging Library.
+ * $Id: JpegDecode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * decoder for JPEG image data.
+ *
+ * history:
+ * 1996-05-02 fl Created
+ * 1996-05-05 fl Handle small JPEG files correctly
+ * 1996-05-28 fl Added "draft mode" support
+ * 1997-01-25 fl Added colour conversion override
+ * 1998-01-31 fl Adapted to libjpeg 6a
+ * 1998-07-12 fl Extended YCbCr support
+ * 1998-12-29 fl Added new state to handle suspension in multipass modes
+ * 2000-10-12 fl Suppress warnings
+ * 2000-12-04 fl Suppress errors beyond end of image data
+ *
+ * Copyright (c) 1998-2000 Secret Labs AB
+ * Copyright (c) 1996-2000 Fredrik Lundh
+ *
+ * See the README file for details on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+#ifdef HAVE_LIBJPEG
+
+#undef HAVE_PROTOTYPES
+#undef HAVE_STDLIB_H
+#undef HAVE_STDDEF_H
+#undef UINT8
+#undef UINT16
+#undef UINT32
+#undef INT16
+#undef INT32
+
+#include "Jpeg.h"
+
+
+/* -------------------------------------------------------------------- */
+/* Suspending input handler */
+/* -------------------------------------------------------------------- */
+
+METHODDEF(void)
+stub(j_decompress_ptr cinfo)
+{
+ /* empty */
+}
+
+METHODDEF(boolean)
+fill_input_buffer(j_decompress_ptr cinfo)
+{
+ /* Suspension */
+ return FALSE;
+}
+
+METHODDEF(void)
+skip_input_data(j_decompress_ptr cinfo, long num_bytes)
+{
+ JPEGSOURCE* source = (JPEGSOURCE*) cinfo->src;
+
+ if (num_bytes > (long) source->pub.bytes_in_buffer) {
+ /* We need to skip more data than we have in the buffer.
+ This will force the JPEG library to suspend decoding. */
+ source->skip = num_bytes - source->pub.bytes_in_buffer;
+ source->pub.next_input_byte += source->pub.bytes_in_buffer;
+ source->pub.bytes_in_buffer = 0;
+ } else {
+ /* Skip portion of the buffer */
+ source->pub.bytes_in_buffer -= num_bytes;
+ source->pub.next_input_byte += num_bytes;
+ source->skip = 0;
+ }
+}
+
+
+GLOBAL(void)
+jpeg_buffer_src(j_decompress_ptr cinfo, JPEGSOURCE* source)
+{
+ cinfo->src = (void*) source;
+
+ /* Prepare for suspending reader */
+ source->pub.init_source = stub;
+ source->pub.fill_input_buffer = fill_input_buffer;
+ source->pub.skip_input_data = skip_input_data;
+ source->pub.resync_to_restart = jpeg_resync_to_restart;
+ source->pub.term_source = stub;
+ source->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
+
+ source->skip = 0;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Error handler */
+/* -------------------------------------------------------------------- */
+
+METHODDEF(void)
+error(j_common_ptr cinfo)
+{
+ JPEGERROR* error;
+ error = (JPEGERROR*) cinfo->err;
+ longjmp(error->setjmp_buffer, 1);
+}
+
+METHODDEF(void)
+output(j_common_ptr cinfo)
+{
+ /* nothing */
+}
+
+/* -------------------------------------------------------------------- */
+/* Decoder */
+/* -------------------------------------------------------------------- */
+
+int
+ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ JPEGSTATE* context = (JPEGSTATE*) state->context;
+ int ok;
+
+ if (setjmp(context->error.setjmp_buffer)) {
+ /* JPEG error handler */
+ jpeg_destroy_decompress(&context->cinfo);
+ state->errcode = IMAGING_CODEC_BROKEN;
+ return -1;
+ }
+
+ if (!state->state) {
+
+ /* Setup decompression context */
+ context->cinfo.err = jpeg_std_error(&context->error.pub);
+ context->error.pub.error_exit = error;
+ context->error.pub.output_message = output;
+ jpeg_create_decompress(&context->cinfo);
+ jpeg_buffer_src(&context->cinfo, &context->source);
+
+ /* Ready to decode */
+ state->state = 1;
+
+ }
+
+ /* Load the source buffer */
+ context->source.pub.next_input_byte = buf;
+ context->source.pub.bytes_in_buffer = bytes;
+
+ if (context->source.skip > 0) {
+ skip_input_data(&context->cinfo, context->source.skip);
+ if (context->source.skip > 0)
+ return context->source.pub.next_input_byte - buf;
+ }
+
+ switch (state->state) {
+
+ case 1:
+
+ /* Read JPEG header, until we find an image body. */
+ do {
+
+ /* Note that we cannot return unless we have decoded
+ as much data as possible. */
+ ok = jpeg_read_header(&context->cinfo, FALSE);
+
+ } while (ok == JPEG_HEADER_TABLES_ONLY);
+
+ if (ok == JPEG_SUSPENDED)
+ break;
+
+ /* Decoder settings */
+
+ /* jpegmode indicates whats in the file; if not set, we'll
+ trust the decoder */
+ if (strcmp(context->jpegmode, "L") == 0)
+ context->cinfo.jpeg_color_space = JCS_GRAYSCALE;
+ else if (strcmp(context->jpegmode, "RGB") == 0)
+ context->cinfo.jpeg_color_space = JCS_RGB;
+ else if (strcmp(context->jpegmode, "CMYK") == 0)
+ context->cinfo.jpeg_color_space = JCS_CMYK;
+ else if (strcmp(context->jpegmode, "YCbCr") == 0)
+ context->cinfo.jpeg_color_space = JCS_YCbCr;
+ else if (strcmp(context->jpegmode, "YCbCrK") == 0) {
+ context->cinfo.jpeg_color_space = JCS_YCCK;
+ }
+
+ /* rawmode indicates what we want from the decoder. if not
+ set, conversions are disabled */
+ if (strcmp(context->rawmode, "L") == 0)
+ context->cinfo.out_color_space = JCS_GRAYSCALE;
+ else if (strcmp(context->rawmode, "RGB") == 0)
+ context->cinfo.out_color_space = JCS_RGB;
+ else if (strcmp(context->rawmode, "CMYK") == 0)
+ context->cinfo.out_color_space = JCS_CMYK;
+ else if (strcmp(context->rawmode, "YCbCr") == 0)
+ context->cinfo.out_color_space = JCS_YCbCr;
+ else if (strcmp(context->rawmode, "YCbCrK") == 0)
+ context->cinfo.out_color_space = JCS_YCCK;
+ else {
+ /* Disable decoder conversions */
+ context->cinfo.jpeg_color_space = JCS_UNKNOWN;
+ context->cinfo.out_color_space = JCS_UNKNOWN;
+ }
+
+ if (context->scale > 1) {
+ context->cinfo.scale_num = 1;
+ context->cinfo.scale_denom = context->scale;
+ }
+ if (context->draft) {
+ context->cinfo.do_fancy_upsampling = FALSE;
+ context->cinfo.dct_method = JDCT_FASTEST;
+ }
+
+ state->state++;
+ /* fall through */
+
+ case 2:
+
+ /* Set things up for decompression (this processes the entire
+ file if necessary to return data line by line) */
+ if (!jpeg_start_decompress(&context->cinfo))
+ break;
+
+ state->state++;
+ /* fall through */
+
+ case 3:
+
+ /* Decompress a single line of data */
+ ok = 1;
+ while (state->y < state->ysize) {
+ ok = jpeg_read_scanlines(&context->cinfo, &state->buffer, 1);
+ if (ok != 1)
+ break;
+ state->shuffle((UINT8*) im->image[state->y + state->yoff] +
+ state->xoff * im->pixelsize, state->buffer,
+ state->xsize);
+ state->y++;
+ }
+ if (ok != 1)
+ break;
+ state->state++;
+ /* fall through */
+
+ case 4:
+
+ /* Finish decompression */
+ if (!jpeg_finish_decompress(&context->cinfo)) {
+ /* FIXME: add strictness mode test */
+ if (state->y < state->ysize)
+ break;
+ }
+
+ /* Clean up */
+ jpeg_destroy_decompress(&context->cinfo);
+ /* if (jerr.pub.num_warnings) return BROKEN; */
+ return -1;
+
+ }
+
+ /* Return number of bytes consumed */
+ return context->source.pub.next_input_byte - buf;
+
+}
+
+#endif
+
diff --git a/Imaging/libImaging/JpegEncode.c b/Imaging/libImaging/JpegEncode.c
new file mode 100644
index 0000000..6bedcd8
--- /dev/null
+++ b/Imaging/libImaging/JpegEncode.c
@@ -0,0 +1,211 @@
+/*
+ * The Python Imaging Library.
+ * $Id: JpegEncode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * coder for JPEG data
+ *
+ * history:
+ * 1996-05-06 fl created
+ * 1996-07-16 fl don't drop last block of encoded data
+ * 1996-12-30 fl added quality and progressive settings
+ * 1997-01-08 fl added streamtype settings
+ * 1998-01-31 fl adapted to libjpeg 6a
+ * 1998-07-12 fl added YCbCr support
+ * 2001-04-16 fl added DPI write support
+ *
+ * Copyright (c) 1997-2001 by Secret Labs AB
+ * Copyright (c) 1995-1997 by Fredrik Lundh
+ *
+ * See the README file for details on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+#ifdef HAVE_LIBJPEG
+
+#undef HAVE_PROTOTYPES
+#undef HAVE_STDLIB_H
+#undef HAVE_STDDEF_H
+#undef UINT8
+#undef UINT16
+#undef UINT32
+#undef INT16
+#undef INT32
+
+#include "Jpeg.h"
+
+/* -------------------------------------------------------------------- */
+/* Suspending output handler */
+/* -------------------------------------------------------------------- */
+
+METHODDEF(void)
+stub(j_compress_ptr cinfo)
+{
+ /* empty */
+}
+
+METHODDEF(boolean)
+empty_output_buffer (j_compress_ptr cinfo)
+{
+ /* Suspension */
+ return FALSE;
+}
+
+GLOBAL(void)
+jpeg_buffer_dest(j_compress_ptr cinfo, JPEGDESTINATION* destination)
+{
+ cinfo->dest = (void*) destination;
+
+ destination->pub.init_destination = stub;
+ destination->pub.empty_output_buffer = empty_output_buffer;
+ destination->pub.term_destination = stub;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Error handler */
+/* -------------------------------------------------------------------- */
+
+METHODDEF(void)
+error(j_common_ptr cinfo)
+{
+ JPEGERROR* error;
+ error = (JPEGERROR*) cinfo->err;
+ (*cinfo->err->output_message) (cinfo);
+ longjmp(error->setjmp_buffer, 1);
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Encoder */
+/* -------------------------------------------------------------------- */
+
+int
+ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ JPEGENCODERSTATE* context = (JPEGENCODERSTATE*) state->context;
+ int ok;
+
+ if (setjmp(context->error.setjmp_buffer)) {
+ /* JPEG error handler */
+ jpeg_destroy_compress(&context->cinfo);
+ state->errcode = IMAGING_CODEC_BROKEN;
+ return -1;
+ }
+
+ if (!state->state) {
+
+ /* Setup compression context (very similar to the decoder) */
+ context->cinfo.err = jpeg_std_error(&context->error.pub);
+ context->error.pub.error_exit = error;
+ jpeg_create_compress(&context->cinfo);
+ jpeg_buffer_dest(&context->cinfo, &context->destination);
+
+ /* Ready to encode */
+ state->state = 1;
+
+ }
+
+ /* Load the destination buffer */
+ context->destination.pub.next_output_byte = buf;
+ context->destination.pub.free_in_buffer = bytes;
+
+ switch (state->state) {
+
+ case 1:
+
+ context->cinfo.image_width = state->xsize;
+ context->cinfo.image_height = state->ysize;
+
+ switch (state->bits) {
+ case 8:
+ context->cinfo.input_components = 1;
+ context->cinfo.in_color_space = JCS_GRAYSCALE;
+ break;
+ case 24:
+ context->cinfo.input_components = 3;
+ if (strcmp(im->mode, "YCbCr") == 0)
+ context->cinfo.in_color_space = JCS_YCbCr;
+ else
+ context->cinfo.in_color_space = JCS_RGB;
+ break;
+ case 32:
+ context->cinfo.input_components = 4;
+ context->cinfo.in_color_space = JCS_CMYK;
+ break;
+ default:
+ state->errcode = IMAGING_CODEC_CONFIG;
+ return -1;
+ }
+
+ /* Compressor configuration */
+ jpeg_set_defaults(&context->cinfo);
+ if (context->quality > 0)
+ jpeg_set_quality(&context->cinfo, context->quality, 1);
+ if (context->progressive)
+ jpeg_simple_progression(&context->cinfo);
+ context->cinfo.smoothing_factor = context->smooth;
+ context->cinfo.optimize_coding = (boolean) context->optimize;
+ if (context->xdpi > 0 && context->ydpi > 0) {
+ context->cinfo.density_unit = 1; /* dots per inch */
+ context->cinfo.X_density = context->xdpi;
+ context->cinfo.Y_density = context->ydpi;
+ }
+ switch (context->streamtype) {
+ case 1:
+ /* tables only -- not yet implemented */
+ state->errcode = IMAGING_CODEC_CONFIG;
+ return -1;
+ case 2:
+ /* image only */
+ jpeg_suppress_tables(&context->cinfo, TRUE);
+ jpeg_start_compress(&context->cinfo, FALSE);
+ break;
+ default:
+ /* interchange stream */
+ jpeg_start_compress(&context->cinfo, TRUE);
+ break;
+ }
+ state->state++;
+ /* fall through */
+
+ case 2:
+
+ ok = 1;
+ while (state->y < state->ysize) {
+ state->shuffle(state->buffer,
+ (UINT8*) im->image[state->y + state->yoff] +
+ state->xoff * im->pixelsize, state->xsize);
+ ok = jpeg_write_scanlines(&context->cinfo, &state->buffer, 1);
+ if (ok != 1)
+ break;
+ state->y++;
+ }
+
+ if (ok != 1)
+ break;
+ state->state++;
+ /* fall through */
+
+ case 3:
+
+ /* Finish compression */
+ if (context->destination.pub.free_in_buffer < 100)
+ break;
+ jpeg_finish_compress(&context->cinfo);
+
+ /* Clean up */
+ jpeg_destroy_compress(&context->cinfo);
+ /* if (jerr.pub.num_warnings) return BROKEN; */
+ state->errcode = IMAGING_CODEC_END;
+ break;
+
+ }
+
+ /* Return number of bytes in output buffer */
+ return context->destination.pub.next_output_byte - buf;
+
+}
+
+#endif
diff --git a/Imaging/libImaging/Lzw.h b/Imaging/libImaging/Lzw.h
new file mode 100644
index 0000000..3e6faa2
--- /dev/null
+++ b/Imaging/libImaging/Lzw.h
@@ -0,0 +1,52 @@
+/*
+ * The Python Imaging Library.
+ * $Id: Lzw.h 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * declarations for the TIFF LZW decoder.
+ *
+ * Copyright (c) Fredrik Lundh 1995-96.
+ */
+
+
+/* Max size for LZW code words */
+
+#define LZWBITS 12
+
+#define LZWTABLE (1<<LZWBITS)
+#define LZWBUFFER (1<<LZWBITS)
+
+
+typedef struct {
+
+ /* CONFIGURATION */
+
+ /* Filter type */
+ int filter;
+
+ /* PRIVATE CONTEXT (set by decoder) */
+
+ /* Input bit buffer */
+ INT32 bitbuffer;
+ int bitcount;
+
+ /* Code buffer */
+ int codesize;
+ int codemask;
+
+ /* Constant symbol codes */
+ int clear, end;
+
+ /* Symbol history */
+ int lastcode;
+ unsigned char lastdata;
+
+ /* History buffer */
+ int bufferindex;
+ unsigned char buffer[LZWTABLE];
+
+ /* Symbol table */
+ unsigned INT16 link[LZWTABLE];
+ unsigned char data[LZWTABLE];
+ int next;
+
+} LZWSTATE;
diff --git a/Imaging/libImaging/LzwDecode.c b/Imaging/libImaging/LzwDecode.c
new file mode 100644
index 0000000..adbaf46
--- /dev/null
+++ b/Imaging/libImaging/LzwDecode.c
@@ -0,0 +1,230 @@
+/*
+ * The Python Imaging Library.
+ * $Id: LzwDecode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * a fast, suspendable TIFF LZW decoder
+ *
+ * description:
+ * This code is based on the GIF decoder. There are some
+ * subtle differences between GIF and TIFF LZW, though:
+ * - The fill order is different. In the TIFF file, you
+ * must shift new bits in to the right, not to the left.
+ * - There is no blocking in the input data stream.
+ * - The code size is increased one step earlier than
+ * for GIF
+ * - Image data are seen as a byte stream, not a pixel
+ * stream. This means that the code size will always
+ * start at 9 bits.
+ *
+ * history:
+ * 95-09-13 fl Created (derived from GifDecode.c)
+ * 96-03-28 fl Revised API, integrated with PIL
+ * 97-01-05 fl Added filter support, added extra consistency checks
+ *
+ * Copyright (c) Fredrik Lundh 1995-97.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+#include <stdio.h>
+#include <stdlib.h> /* memcpy() */
+
+#include "Lzw.h"
+
+
+int
+ImagingLzwDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ UINT8* p;
+ int c, i;
+ int thiscode;
+ LZWSTATE* context = (LZWSTATE*) state->context;
+
+ unsigned char *ptr = buf;
+
+ if (!state->state) {
+
+ /* Clear code */
+ context->clear = 1 << 8;
+
+ /* End code */
+ context->end = context->clear + 1;
+
+ state->state = 1;
+ }
+
+ for (;;) {
+
+ if (state->state == 1) {
+
+ /* First free entry in table */
+ context->next = context->clear + 2;
+
+ /* Initial code size */
+ context->codesize = 8 + 1;
+ context->codemask = (1 << context->codesize) - 1;
+
+ /* Buffer pointer. We fill the buffer from right, which
+ allows us to return all of it in one operation. */
+ context->bufferindex = LZWBUFFER;
+
+ state->state = 2;
+ }
+
+ if (context->bufferindex < LZWBUFFER) {
+
+ /* Return whole buffer in one chunk */
+ i = LZWBUFFER - context->bufferindex;
+ p = &context->buffer[context->bufferindex];
+
+ context->bufferindex = LZWBUFFER;
+
+ } else {
+
+ /* Get current symbol */
+ while (context->bitcount < context->codesize) {
+
+ if (bytes < 1)
+ return ptr - buf;;
+
+ /* Read next byte */
+ c = *ptr++; bytes--;
+
+ /* New bits are shifted in from from the right. */
+ context->bitbuffer = (context->bitbuffer << 8) | c;
+ context->bitcount += 8;
+
+ }
+
+ /* Extract current symbol from bit buffer. */
+ c = (context->bitbuffer >> (context->bitcount -
+ context->codesize))
+ & context->codemask;
+
+ /* Adjust buffer */
+ context->bitcount -= context->codesize;
+
+ /* If c is less than clear, it's a data byte. Otherwise,
+ it's either clear/end or a code symbol which should be
+ expanded. */
+
+ if (c == context->clear) {
+ if (state->state != 2)
+ state->state = 1;
+ continue;
+ }
+
+ if (c == context->end)
+ break;
+
+ i = 1;
+ p = &context->lastdata;
+
+ if (state->state == 2) {
+
+ /* First valid symbol after clear; use as is */
+ if (c > context->clear) {
+ state->errcode = IMAGING_CODEC_BROKEN;
+ return -1;
+ }
+
+ context->lastdata = context->lastcode = c;
+ state->state = 3;
+
+ } else {
+
+ thiscode = c;
+
+ if (c > context->next) {
+ state->errcode = IMAGING_CODEC_BROKEN;
+ return -1;
+ }
+
+ if (c == context->next) {
+
+ /* c == next is allowed, by some strange reason */
+ if (context->bufferindex <= 0) {
+ state->errcode = IMAGING_CODEC_BROKEN;
+ return -1;
+ }
+
+ context->buffer[--context->bufferindex] = context->lastdata;
+ c = context->lastcode;
+ }
+
+ while (c >= context->clear) {
+
+ /* Copy data string to buffer (beginning from right) */
+
+ if (context->bufferindex <= 0 || c >= LZWTABLE) {
+ state->errcode = IMAGING_CODEC_BROKEN;
+ return -1;
+ }
+
+ context->buffer[--context->bufferindex] =
+ context->data[c];
+ c = context->link[c];
+ }
+
+ context->lastdata = c;
+
+ if (context->next < LZWTABLE) {
+
+ /* While we still have room for it, add this
+ symbol to the table. */
+ context->data[context->next] = c;
+ context->link[context->next] = context->lastcode;
+
+ context->next++;
+
+ if (context->next == context->codemask &&
+ context->codesize < LZWBITS) {
+
+ /* Expand code size */
+ context->codesize++;
+ context->codemask = (1 << context->codesize) - 1;
+
+ }
+ }
+ context->lastcode = thiscode;
+ }
+ }
+
+ /* Update the output image */
+ for (c = 0; c < i; c++) {
+
+ state->buffer[state->x] = p[c];
+
+ if (++state->x >= state->bytes) {
+
+ int x, bpp;
+
+ /* Apply filter */
+ switch (context->filter) {
+ case 2:
+ /* Horizontal differing ("prior") */
+ bpp = (state->bits + 7) / 8;
+ for (x = bpp; x < state->bytes; x++)
+ state->buffer[x] += state->buffer[x-bpp];
+ }
+
+ /* Got a full line, unpack it */
+ state->shuffle((UINT8*) im->image[state->y + state->yoff] +
+ state->xoff * im->pixelsize, state->buffer,
+ state->xsize);
+
+ state->x = 0;
+
+ if (++state->y >= state->ysize)
+ /* End of file (errcode = 0) */
+ return -1;
+ }
+ }
+ }
+
+ return ptr - buf;
+}
diff --git a/Imaging/libImaging/Matrix.c b/Imaging/libImaging/Matrix.c
new file mode 100644
index 0000000..08010a7
--- /dev/null
+++ b/Imaging/libImaging/Matrix.c
@@ -0,0 +1,74 @@
+/*
+ * The Python Imaging Library
+ * $Id: Matrix.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * colour and luminance matrix transforms
+ *
+ * history:
+ * 1996-05-18 fl: created (brute force implementation)
+ *
+ * Copyright (c) Fredrik Lundh 1996.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+#define CLIPF(v) ((v <= 0.0) ? 0 : (v >= 255.0F) ? 255 : (UINT8) v)
+
+
+Imaging
+ImagingConvertMatrix(Imaging im, const char *mode, float m[])
+{
+ Imaging imOut;
+ int x, y;
+
+ /* Assume there's enough data in the buffer */
+ if (!im)
+ return (Imaging) ImagingError_ModeError();
+
+ if (strcmp(mode, "L") == 0 && im->bands == 3) {
+
+ imOut = ImagingNew("L", im->xsize, im->ysize);
+ if (!imOut)
+ return NULL;
+
+ for (y = 0; y < im->ysize; y++) {
+ UINT8* in = (UINT8*) im->image[y];
+ UINT8* out = (UINT8*) imOut->image[y];
+
+ for (x = 0; x < im->xsize; x++) {
+ float v = m[0]*in[0] + m[1]*in[1] + m[2]*in[2] + m[3] + 0.5;
+ out[x] = CLIPF(v);
+ in += 4;
+ }
+ }
+
+ } else if (strlen(mode) == 3 && im->bands == 3) {
+
+ imOut = ImagingNew(mode, im->xsize, im->ysize);
+ if (!imOut)
+ return NULL;
+
+ for (y = 0; y < im->ysize; y++) {
+ UINT8* in = (UINT8*) im->image[y];
+ UINT8* out = (UINT8*) imOut->image[y];
+
+ for (x = 0; x < im->xsize; x++) {
+ float v0 = m[0]*in[0] + m[1]*in[1] + m[2]*in[2] + m[3] + 0.5;
+ float v1 = m[4]*in[0] + m[5]*in[1] + m[6]*in[2] + m[7] + 0.5;
+ float v2 = m[8]*in[0] + m[9]*in[1] + m[10]*in[2] + m[11] + 0.5;
+ out[0] = CLIPF(v0);
+ out[1] = CLIPF(v1);
+ out[2] = CLIPF(v2);
+ in += 4; out += 4;
+ }
+ }
+ } else
+ return (Imaging) ImagingError_ModeError();
+
+ return imOut;
+}
diff --git a/Imaging/libImaging/ModeFilter.c b/Imaging/libImaging/ModeFilter.c
new file mode 100644
index 0000000..b3a9045
--- /dev/null
+++ b/Imaging/libImaging/ModeFilter.c
@@ -0,0 +1,78 @@
+/*
+ * The Python Imaging Library
+ * $Id: ModeFilter.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * mode filter
+ *
+ * history:
+ * 2002-06-08 fl Created (based on code from IFUNC95)
+ * 2004-10-05 fl Rewritten; use a simpler brute-force algorithm
+ *
+ * Copyright (c) Secret Labs AB 2002-2004. All rights reserved.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+#include "Imaging.h"
+
+Imaging
+ImagingModeFilter(Imaging im, int size)
+{
+ Imaging imOut;
+ int x, y, i;
+ int xx, yy;
+ int maxcount;
+ UINT8 maxpixel;
+ int histogram[256];
+
+ if (!im || im->bands != 1 || im->type != IMAGING_TYPE_UINT8)
+ return (Imaging) ImagingError_ModeError();
+
+ imOut = ImagingNew(im->mode, im->xsize, im->ysize);
+ if (!imOut)
+ return NULL;
+
+ size = size / 2;
+
+ for (y = 0; y < imOut->ysize; y++) {
+ UINT8* out = &IMAGING_PIXEL_L(imOut, 0, y);
+ for (x = 0; x < imOut->xsize; x++) {
+
+ /* calculate histogram over current area */
+
+ /* FIXME: brute force! to improve, update the histogram
+ incrementally. may also add a "frequent list", like in
+ the old implementation, but I'm not sure that's worth
+ the added complexity... */
+
+ memset(histogram, 0, sizeof(histogram));
+ for (yy = y - size; yy <= y + size; yy++)
+ if (yy >= 0 && yy < imOut->ysize) {
+ UINT8* in = &IMAGING_PIXEL_L(im, 0, yy);
+ for (xx = x - size; xx <= x + size; xx++)
+ if (xx >= 0 && xx < imOut->xsize)
+ histogram[in[xx]]++;
+ }
+
+ /* find most frequent pixel value in this region */
+ maxpixel = 0;
+ maxcount = histogram[maxpixel];
+ for (i = 1; i < 256; i++)
+ if (histogram[i] > maxcount) {
+ maxcount = histogram[i];
+ maxpixel = (UINT8) i;
+ }
+
+ if (maxcount > 2)
+ out[x] = maxpixel;
+ else
+ out[x] = IMAGING_PIXEL_L(im, x, y);
+
+ }
+
+ }
+
+ ImagingCopyInfo(imOut, im);
+
+ return imOut;
+}
diff --git a/Imaging/libImaging/MspDecode.c b/Imaging/libImaging/MspDecode.c
new file mode 100644
index 0000000..af2b842
--- /dev/null
+++ b/Imaging/libImaging/MspDecode.c
@@ -0,0 +1,91 @@
+/*
+ * The Python Imaging Library.
+ * $Id: MspDecode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * decoder for MSP version 2 data.
+ *
+ * history:
+ * 97-01-03 fl Created
+ *
+ * Copyright (c) Fredrik Lundh 1997.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+int
+ImagingMspDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ int n;
+ UINT8* ptr;
+
+ ptr = buf;
+
+ for (;;) {
+
+ if (bytes < 1)
+ return ptr - buf;
+
+ if (ptr[0] == 0) {
+
+ /* Run (3 bytes block) */
+ if (bytes < 3)
+ break;
+
+ n = ptr[1];
+
+ if (state->x + n > state->bytes) {
+ state->errcode = IMAGING_CODEC_OVERRUN;
+ return -1;
+ }
+
+ memset(state->buffer + state->x, ptr[2], n);
+
+ ptr += 3;
+ bytes -= 3;
+
+ } else {
+
+ /* Literal (1+n bytes block) */
+ n = ptr[0];
+
+ if (bytes < 1 + n)
+ break;
+
+ if (state->x + n > state->bytes) {
+ state->errcode = IMAGING_CODEC_OVERRUN;
+ return -1;
+ }
+
+ memcpy(state->buffer + state->x, ptr + 1, n);
+
+ ptr += 1 + n;
+ bytes -= 1 + n;
+
+ }
+
+ state->x += n;
+
+ if (state->x >= state->bytes) {
+
+ /* Got a full line, unpack it */
+ state->shuffle((UINT8*) im->image[state->y + state->yoff] +
+ state->xoff * im->pixelsize, state->buffer,
+ state->xsize);
+
+ state->x = 0;
+
+ if (++state->y >= state->ysize) {
+ /* End of file (errcode = 0) */
+ return -1;
+ }
+ }
+
+ }
+
+ return ptr - buf;
+}
diff --git a/Imaging/libImaging/Negative.c b/Imaging/libImaging/Negative.c
new file mode 100644
index 0000000..1255525
--- /dev/null
+++ b/Imaging/libImaging/Negative.c
@@ -0,0 +1,42 @@
+/*
+ * The Python Imaging Library
+ * $Id: Negative.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * negate image
+ *
+ * to do:
+ * FIXME: Maybe this should be implemented using ImagingPoint()
+ *
+ * history:
+ * 95-11-27 fl: Created
+ *
+ * Copyright (c) Fredrik Lundh 1995.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+Imaging
+ImagingNegative(Imaging im)
+{
+ Imaging imOut;
+ int x, y;
+
+ if (!im)
+ return (Imaging) ImagingError_ModeError();
+
+ imOut = ImagingNew(im->mode, im->xsize, im->ysize);
+ if (!imOut)
+ return NULL;
+
+ for (y = 0; y < im->ysize; y++)
+ for (x = 0; x < im->linesize; x++)
+ imOut->image[y][x] = ~im->image[y][x];
+
+ return imOut;
+}
+
diff --git a/Imaging/libImaging/Offset.c b/Imaging/libImaging/Offset.c
new file mode 100644
index 0000000..7e5ac14
--- /dev/null
+++ b/Imaging/libImaging/Offset.c
@@ -0,0 +1,61 @@
+/*
+ * The Python Imaging Library
+ * $Id: Offset.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * offset an image in x and y directions
+ *
+ * history:
+ * 96-07-22 fl: Created
+ * 98-11-01 cgw@pgt.com: Fixed negative-array index bug
+ *
+ * Copyright (c) Fredrik Lundh 1996.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+Imaging
+ImagingOffset(Imaging im, int xoffset, int yoffset)
+{
+ int x, y;
+ Imaging imOut;
+
+ if (!im)
+ return (Imaging) ImagingError_ModeError();
+
+ imOut = ImagingNew(im->mode, im->xsize, im->ysize);
+ if (!imOut)
+ return NULL;
+
+ ImagingCopyInfo(imOut, im);
+
+ /* make offsets positive to avoid negative coordinates */
+ xoffset %= im->xsize;
+ xoffset = im->xsize - xoffset;
+ if (xoffset < 0)
+ xoffset += im->xsize;
+
+ yoffset %= im->ysize;
+ yoffset = im->ysize - yoffset;
+ if (yoffset < 0)
+ yoffset += im->ysize;
+
+#define OFFSET(image)\
+ for (y = 0; y < im->ysize; y++)\
+ for (x = 0; x < im->xsize; x++) {\
+ int yi = (y + yoffset) % im->ysize;\
+ int xi = (x + xoffset) % im->xsize;\
+ imOut->image[y][x] = im->image[yi][xi];\
+ }
+
+ if (im->image8)
+ OFFSET(image8)
+ else
+ OFFSET(image32)
+
+ return imOut;
+}
diff --git a/Imaging/libImaging/Pack.c b/Imaging/libImaging/Pack.c
new file mode 100644
index 0000000..8e261f6
--- /dev/null
+++ b/Imaging/libImaging/Pack.c
@@ -0,0 +1,531 @@
+/*
+ * The Python Imaging Library.
+ * $Id: Pack.c 2763 2006-06-22 21:43:28Z fredrik $
+ *
+ * code to pack raw data
+ *
+ * history:
+ * 1996-04-30 fl Created
+ * 1996-05-12 fl Published a few RGB packers
+ * 1996-11-01 fl More RGB packers (Tk booster stuff)
+ * 1996-12-30 fl Added P;1, P;2 and P;4 packers
+ * 1997-06-02 fl Added F (F;32NF) packer
+ * 1997-08-28 fl Added 1 as L packer
+ * 1998-02-08 fl Added I packer
+ * 1998-03-09 fl Added mode field, RGBA/RGBX as RGB packers
+ * 1998-07-01 fl Added YCbCr support
+ * 1998-07-12 fl Added I 16 packer
+ * 1999-02-03 fl Added BGR packers
+ * 2003-09-26 fl Added LA/PA packers
+ * 2006-06-22 fl Added CMYK;I packer
+ *
+ * Copyright (c) 1997-2006 by Secret Labs AB.
+ * Copyright (c) 1996-1997 by Fredrik Lundh.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+#define R 0
+#define G 1
+#define B 2
+#define X 3
+#define A 3
+
+#define C 0
+#define M 1
+#define Y 2
+#define K 3
+
+/* byte swapping macros */
+
+#define C16N\
+ (out[0]=tmp[0], out[1]=tmp[1]);
+#define C16S\
+ (out[1]=tmp[0], out[0]=tmp[1]);
+#define C32N\
+ (out[0]=tmp[0], out[1]=tmp[1], out[2]=tmp[2], out[3]=tmp[3]);
+#define C32S\
+ (out[3]=tmp[0], out[2]=tmp[1], out[1]=tmp[2], out[0]=tmp[3]);
+#define C64N\
+ (out[0]=tmp[0], out[1]=tmp[1], out[2]=tmp[2], out[3]=tmp[3],\
+ out[4]=tmp[4], out[5]=tmp[5], out[6]=tmp[6], out[7]=tmp[7]);
+#define C64S\
+ (out[7]=tmp[0], out[6]=tmp[1], out[5]=tmp[2], out[4]=tmp[3],\
+ out[3]=tmp[4], out[2]=tmp[5], out[1]=tmp[6], out[0]=tmp[7]);
+
+#ifdef WORDS_BIGENDIAN
+#define C16B C16N
+#define C16L C16S
+#define C32B C32N
+#define C32L C32S
+#define C64B C64N
+#define C64L C64S
+#else
+#define C16B C16S
+#define C16L C16N
+#define C32B C32S
+#define C32L C32N
+#define C64B C64S
+#define C64L C64N
+#endif
+
+static void
+pack1(UINT8* out, const UINT8* in, int pixels)
+{
+ int i, m, b;
+ /* bilevel (black is 0) */
+ b = 0; m = 128;
+ for (i = 0; i < pixels; i++) {
+ if (in[i] != 0)
+ b |= m;
+ m >>= 1;
+ if (m == 0) {
+ *out++ = b;
+ b = 0; m = 128;
+ }
+ }
+ if (m != 128)
+ *out++ = b;
+}
+
+static void
+pack1I(UINT8* out, const UINT8* in, int pixels)
+{
+ int i, m, b;
+ /* bilevel (black is 1) */
+ b = 0; m = 128;
+ for (i = 0; i < pixels; i++) {
+ if (in[i] == 0)
+ b |= m;
+ m >>= 1;
+ if (m == 0) {
+ *out++ = b;
+ b = 0; m = 128;
+ }
+ }
+ if (m != 128)
+ *out++ = b;
+}
+
+static void
+pack1R(UINT8* out, const UINT8* in, int pixels)
+{
+ int i, m, b;
+ /* bilevel, lsb first (black is 0) */
+ b = 0; m = 1;
+ for (i = 0; i < pixels; i++) {
+ if (in[i] != 0)
+ b |= m;
+ m <<= 1;
+ if (m == 256){
+ *out++ = b;
+ b = 0; m = 1;
+ }
+ }
+ if (m != 1)
+ *out++ = b;
+}
+
+static void
+pack1IR(UINT8* out, const UINT8* in, int pixels)
+{
+ int i, m, b;
+ /* bilevel, lsb first (black is 1) */
+ b = 0; m = 1;
+ for (i = 0; i < pixels; i++) {
+ if (in[i] == 0)
+ b |= m;
+ m <<= 1;
+ if (m == 256){
+ *out++ = b;
+ b = 0; m = 1;
+ }
+ }
+ if (m != 1)
+ *out++ = b;
+}
+
+static void
+pack1L(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* bilevel, stored as bytes */
+ for (i = 0; i < pixels; i++)
+ out[i] = (in[i] != 0) ? 255 : 0;
+}
+
+static void
+packP4(UINT8* out, const UINT8* in, int pixels)
+{
+ while (pixels >= 2) {
+ *out++ = (in[0] << 4) |
+ (in[1] & 15);
+ in += 2; pixels -= 2;
+ }
+
+ if (pixels)
+ out[0] = (in[0] << 4);
+}
+
+static void
+packP2(UINT8* out, const UINT8* in, int pixels)
+{
+ while (pixels >= 4) {
+ *out++ = (in[0] << 6) |
+ ((in[1] & 3) << 4) |
+ ((in[2] & 3) << 2) |
+ (in[3] & 3);
+ in += 4; pixels -= 4;
+ }
+
+ switch (pixels) {
+ case 3:
+ out[0] = (in[0] << 6) |
+ ((in[1] & 3) << 4) |
+ ((in[2] & 3) << 2);
+ break;
+ case 2:
+ out[0] = (in[0] << 6) |
+ ((in[1] & 3) << 4);
+ case 1:
+ out[0] = (in[0] << 6);
+ }
+}
+
+static void
+packLA(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* LA, pixel interleaved */
+ for (i = 0; i < pixels; i++) {
+ out[0] = in[R];
+ out[1] = in[A];
+ out += 2; in += 4;
+ }
+}
+
+static void
+packLAL(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* LA, line interleaved */
+ for (i = 0; i < pixels; i++) {
+ out[i] = in[R];
+ out[i+pixels] = in[A];
+ in += 4;
+ }
+}
+
+void
+ImagingPackRGB(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* RGB triplets */
+ for (i = 0; i < pixels; i++) {
+ out[0] = in[R];
+ out[1] = in[G];
+ out[2] = in[B];
+ out += 3; in += 4;
+ }
+}
+
+void
+ImagingPackXRGB(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* XRGB, triplets with left padding */
+ for (i = 0; i < pixels; i++) {
+ out[0] = 0;
+ out[1] = in[R];
+ out[2] = in[G];
+ out[3] = in[B];
+ out += 4; in += 4;
+ }
+}
+
+void
+ImagingPackBGR(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* RGB, reversed bytes */
+ for (i = 0; i < pixels; i++) {
+ out[0] = in[B];
+ out[1] = in[G];
+ out[2] = in[R];
+ out += 3; in += 4;
+ }
+}
+
+void
+ImagingPackBGRX(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] = 0;
+ out += 4; in += 4;
+ }
+}
+
+void
+ImagingPackXBGR(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* XBGR, reversed bytes with left padding */
+ for (i = 0; i < pixels; i++) {
+ out[0] = 0;
+ 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)
+{
+ int i;
+ /* RGB, line interleaved */
+ for (i = 0; i < pixels; i++) {
+ out[i] = in[R];
+ out[i+pixels] = in[G];
+ out[i+pixels+pixels] = in[B];
+ in += 4;
+ }
+}
+
+static void
+packRGBXL(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* RGBX, line interleaved */
+ for (i = 0; i < pixels; i++) {
+ out[i] = in[R];
+ out[i+pixels] = in[G];
+ out[i+pixels+pixels] = in[B];
+ out[i+pixels+pixels+pixels] = in[X];
+ in += 4;
+ }
+}
+
+static void
+packI16B(UINT8* out, const UINT8* in_, int pixels)
+{
+ int i;
+ INT32* in = (INT32*) in_;
+ UINT16 tmp_;
+ UINT8* tmp = (UINT8*) &tmp_;
+ for (i = 0; i < pixels; i++) {
+ if (in[0] <= 0)
+ tmp_ = 0;
+ else if (in[0] > 65535)
+ tmp_ = 65535;
+ else
+ tmp_ = in[0];
+ C16B;
+ out += 2; in++;
+ }
+}
+
+static void
+packI32S(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ UINT8* tmp = (UINT8*) in;
+ for (i = 0; i < pixels; i++) {
+ C32L;
+ out += 4; tmp += 4;
+ }
+}
+
+static void
+copy1(UINT8* out, const UINT8* in, int pixels)
+{
+ /* L, P */
+ memcpy(out, in, pixels);
+}
+
+static void
+copy2(UINT8* out, const UINT8* in, int pixels)
+{
+ /* I;16, etc */
+ memcpy(out, in, pixels*2);
+}
+
+static void
+copy3(UINT8* out, const UINT8* in, int pixels)
+{
+ /* BGR;24, etc */
+ memcpy(out, in, pixels*3);
+}
+
+static void
+copy4(UINT8* out, const UINT8* in, int pixels)
+{
+ /* RGBA, CMYK quadruples */
+ memcpy(out, in, 4*pixels);
+}
+
+static void
+copy4I(UINT8* out, const UINT8* in, int pixels)
+{
+ /* RGBA, CMYK quadruples, inverted */
+ int i;
+ for (i = 0; i < pixels*4; i++)
+ out[i] = ~in[i];
+}
+
+static void
+band0(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ for (i = 0; i < pixels; i++, in += 4)
+ out[i] = in[0];
+}
+
+static void
+band1(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ for (i = 0; i < pixels; i++, in += 4)
+ out[i] = in[1];
+}
+
+static void
+band2(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ for (i = 0; i < pixels; i++, in += 4)
+ out[i] = in[2];
+}
+
+static void
+band3(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ for (i = 0; i < pixels; i++, in += 4)
+ out[i] = in[3];
+}
+
+static struct {
+ const char* mode;
+ const char* rawmode;
+ int bits;
+ ImagingShuffler pack;
+} packers[] = {
+
+ /* bilevel */
+ {"1", "1", 1, pack1},
+ {"1", "1;I", 1, pack1I},
+ {"1", "1;R", 1, pack1R},
+ {"1", "1;IR", 1, pack1IR},
+ {"1", "L", 8, pack1L},
+
+ /* greyscale */
+ {"L", "L", 8, copy1},
+
+ /* greyscale w. alpha */
+ {"LA", "LA", 16, packLA},
+ {"LA", "LA;L", 16, packLAL},
+
+ /* palette */
+ {"P", "P;1", 1, pack1},
+ {"P", "P;2", 2, packP2},
+ {"P", "P;4", 4, packP4},
+ {"P", "P", 8, copy1},
+
+ /* palette w. alpha */
+ {"PA", "PA", 16, packLA},
+ {"PA", "PA;L", 16, packLAL},
+
+ /* true colour */
+ {"RGB", "RGB", 24, ImagingPackRGB},
+ {"RGB", "RGBX", 32, copy4},
+ {"RGB", "XRGB", 32, ImagingPackXRGB},
+ {"RGB", "BGR", 24, ImagingPackBGR},
+ {"RGB", "BGRX", 32, ImagingPackBGRX},
+ {"RGB", "XBGR", 32, ImagingPackXBGR},
+ {"RGB", "RGB;L", 24, packRGBL},
+ {"RGB", "R", 8, band0},
+ {"RGB", "G", 8, band1},
+ {"RGB", "B", 8, band2},
+
+ /* true colour w. alpha */
+ {"RGBA", "RGBA", 32, copy4},
+ {"RGBA", "RGBA;L", 32, packRGBXL},
+ {"RGBA", "RGB", 24, ImagingPackRGB},
+ {"RGBA", "R", 8, band0},
+ {"RGBA", "G", 8, band1},
+ {"RGBA", "B", 8, band2},
+ {"RGBA", "A", 8, band3},
+
+ /* true colour w. padding */
+ {"RGBX", "RGBX", 32, copy4},
+ {"RGBX", "RGBX;L", 32, packRGBXL},
+ {"RGBX", "RGB", 32, ImagingPackRGB},
+ {"RGBX", "R", 8, band0},
+ {"RGBX", "G", 8, band1},
+ {"RGBX", "B", 8, band2},
+ {"RGBX", "X", 8, band3},
+
+ /* colour separation */
+ {"CMYK", "CMYK", 32, copy4},
+ {"CMYK", "CMYK;I", 32, copy4I},
+ {"CMYK", "CMYK;L", 32, packRGBXL},
+ {"CMYK", "C", 8, band0},
+ {"CMYK", "M", 8, band1},
+ {"CMYK", "Y", 8, band2},
+ {"CMYK", "K", 8, band3},
+
+ /* video (YCbCr) */
+ {"YCbCr", "YCbCr", 24, ImagingPackRGB},
+ {"YCbCr", "YCbCr;L", 24, packRGBL},
+ {"YCbCr", "YCbCrX", 32, copy4},
+ {"YCbCr", "YCbCrK", 32, copy4},
+ {"YCbCr", "Y", 8, band0},
+ {"YCbCr", "Cb", 8, band1},
+ {"YCbCr", "Cr", 8, band2},
+
+ /* integer */
+ {"I", "I", 32, copy4},
+ {"I", "I;16B", 16, packI16B},
+ {"I", "I;32S", 32, packI32S},
+ {"I", "I;32NS", 32, copy4},
+
+ /* floating point */
+ {"F", "F", 32, copy4},
+ {"F", "F;32F", 32, packI32S},
+ {"F", "F;32NF", 32, copy4},
+
+ /* storage modes */
+ {"I;16", "I;16", 16, copy2},
+ {"I;16B", "I;16B", 16, copy2},
+ {"BGR;15", "BGR;15", 16, copy2},
+ {"BGR;16", "BGR;16", 16, copy2},
+ {"BGR;24", "BGR;24", 24, copy3},
+
+ {NULL} /* sentinel */
+};
+
+
+ImagingShuffler
+ImagingFindPacker(const char* mode, const char* rawmode, int* bits_out)
+{
+ int i;
+
+ /* find a suitable pixel packer */
+ for (i = 0; packers[i].rawmode; i++)
+ if (strcmp(packers[i].mode, mode) == 0 &&
+ strcmp(packers[i].rawmode, rawmode) == 0) {
+ if (bits_out)
+ *bits_out = packers[i].bits;
+ return packers[i].pack;
+ }
+ return NULL;
+}
diff --git a/Imaging/libImaging/PackDecode.c b/Imaging/libImaging/PackDecode.c
new file mode 100644
index 0000000..267aa85
--- /dev/null
+++ b/Imaging/libImaging/PackDecode.c
@@ -0,0 +1,92 @@
+/*
+ * The Python Imaging Library.
+ * $Id: PackDecode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * decoder for PackBits image data.
+ *
+ * history:
+ * 96-04-19 fl Created
+ *
+ * Copyright (c) Fredrik Lundh 1996.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+int
+ImagingPackbitsDecode(Imaging im, ImagingCodecState state,
+ UINT8* buf, int bytes)
+{
+ UINT8 n;
+ UINT8* ptr;
+ int i;
+
+ ptr = buf;
+
+ for (;;) {
+
+ if (bytes < 1)
+ return ptr - buf;
+
+ if (ptr[0] & 0x80) {
+
+ if (ptr[0] == 0x80) {
+ /* Nop */
+ ptr++; bytes--;
+ continue;
+ }
+
+ /* Run */
+ if (bytes < 2)
+ return ptr - buf;
+
+ for (n = 257 - ptr[0]; n > 0; n--) {
+ if (state->x >= state->bytes) {
+ /* state->errcode = IMAGING_CODEC_OVERRUN; */
+ break;
+ }
+ state->buffer[state->x++] = ptr[1];
+ }
+
+ ptr += 2; bytes -= 2;
+
+ } else {
+
+ /* Literal */
+ n = ptr[0]+2;
+
+ if (bytes < n)
+ return ptr - buf;
+
+ for (i = 1; i < n; i++) {
+ if (state->x >= state->bytes) {
+ /* state->errcode = IMAGING_CODEC_OVERRUN; */
+ break;
+ }
+ state->buffer[state->x++] = ptr[i];
+ }
+
+ ptr += n; bytes -= n;
+
+ }
+
+ if (state->x >= state->bytes) {
+
+ /* Got a full line, unpack it */
+ state->shuffle((UINT8*) im->image[state->y + state->yoff] +
+ state->xoff * im->pixelsize, state->buffer,
+ state->xsize);
+
+ state->x = 0;
+
+ if (++state->y >= state->ysize) {
+ /* End of file (errcode = 0) */
+ return -1;
+ }
+ }
+
+ }
+}
diff --git a/Imaging/libImaging/Palette.c b/Imaging/libImaging/Palette.c
new file mode 100644
index 0000000..02e9e4f
--- /dev/null
+++ b/Imaging/libImaging/Palette.c
@@ -0,0 +1,316 @@
+/*
+ * The Python Imaging Library
+ * $Id: Palette.c 2591 2005-12-08 21:25:29Z fredrik $
+ *
+ * imaging palette object
+ *
+ * history:
+ * 1996-05-05 fl Added to library
+ * 1996-05-27 fl Added colour mapping stuff
+ * 1997-05-12 fl Support RGBA palettes
+ * 2005-02-09 fl Removed grayscale entries from web palette
+ *
+ * Copyright (c) Secret Labs AB 1997-2005. All rights reserved.
+ * Copyright (c) Fredrik Lundh 1995-1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+#include <math.h>
+
+
+ImagingPalette
+ImagingPaletteNew(const char* mode)
+{
+ /* Create a palette object */
+
+ int i;
+ ImagingPalette palette;
+
+ if (strcmp(mode, "RGB") && strcmp(mode, "RGBA"))
+ return (ImagingPalette) ImagingError_ModeError();
+
+ palette = calloc(1, sizeof(struct ImagingPaletteInstance));
+ if (!palette)
+ return (ImagingPalette) ImagingError_MemoryError();
+
+ strcpy(palette->mode, mode);
+
+ /* Initialize to ramp */
+ for (i = 0; i < 256; i++) {
+ palette->palette[i*4+0] =
+ palette->palette[i*4+1] =
+ palette->palette[i*4+2] = (UINT8) i;
+ palette->palette[i*4+3] = 255; /* opaque */
+ }
+
+ return palette;
+}
+
+ImagingPalette
+ImagingPaletteNewBrowser(void)
+{
+ /* Create a standard "browser" palette object */
+
+ int i, r, g, b;
+ ImagingPalette palette;
+
+ palette = ImagingPaletteNew("RGB");
+ if (!palette)
+ return NULL;
+
+ /* Blank out unused entries */
+ /* FIXME: Add 10-level windows palette here? */
+
+ for (i = 0; i < 10; i++) {
+ palette->palette[i*4+0] =
+ palette->palette[i*4+1] =
+ palette->palette[i*4+2] = 0;
+ }
+
+ /* Simple 6x6x6 colour cube */
+
+ for (b = 0; b < 256; b += 51)
+ for (g = 0; g < 256; g += 51)
+ for (r = 0; r < 256; r += 51) {
+ palette->palette[i*4+0] = r;
+ palette->palette[i*4+1] = g;
+ palette->palette[i*4+2] = b;
+ i++;
+ }
+
+ /* Blank out unused entries */
+ /* FIXME: add 30-level greyscale wedge here? */
+
+ for (; i < 256; i++) {
+ palette->palette[i*4+0] =
+ palette->palette[i*4+1] =
+ palette->palette[i*4+2] = 0;
+ }
+
+ return palette;
+}
+
+ImagingPalette
+ImagingPaletteDuplicate(ImagingPalette palette)
+{
+ /* Duplicate palette descriptor */
+
+ ImagingPalette new_palette;
+
+ if (!palette)
+ return NULL;
+
+ new_palette = malloc(sizeof(struct ImagingPaletteInstance));
+ if (!new_palette)
+ return (ImagingPalette) ImagingError_MemoryError();
+
+ memcpy(new_palette, palette, sizeof(struct ImagingPaletteInstance));
+
+ /* Don't share the cache */
+ new_palette->cache = NULL;
+
+ return new_palette;
+}
+
+void
+ImagingPaletteDelete(ImagingPalette palette)
+{
+ /* Destroy palette object */
+
+ if (palette) {
+ if (palette->cache)
+ free(palette->cache);
+ free(palette);
+ }
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Colour mapping */
+/* -------------------------------------------------------------------- */
+
+/* This code is used to map RGB triplets to palette indices, using
+ a palette index cache. */
+
+/*
+ * This implementation is loosely based on the corresponding code in
+ * the IJG JPEG library by Thomas G. Lane. Original algorithms by
+ * Paul Heckbert and Spencer W. Thomas.
+ *
+ * The IJG JPEG library is copyright (C) 1991-1995, Thomas G. Lane. */
+
+#define DIST(a, b, s) (a - b) * (a - b) * s
+
+/* Colour weights (no scaling, for now) */
+#define RSCALE 1
+#define GSCALE 1
+#define BSCALE 1
+
+/* Calculated scaled distances */
+#define RDIST(a, b) DIST(a, b, RSCALE*RSCALE)
+#define GDIST(a, b) DIST(a, b, GSCALE*GSCALE)
+#define BDIST(a, b) DIST(a, b, BSCALE*BSCALE)
+
+/* Incremental steps */
+#define RSTEP (4 * RSCALE)
+#define GSTEP (4 * GSCALE)
+#define BSTEP (4 * BSCALE)
+
+#define BOX 8
+
+#define BOXVOLUME BOX*BOX*BOX
+
+void
+ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b)
+{
+ int i, j;
+ unsigned int dmin[256], dmax;
+ int r0, g0, b0;
+ int r1, g1, b1;
+ int rc, gc, bc;
+ unsigned int d[BOXVOLUME];
+ UINT8 c[BOXVOLUME];
+
+ /* Get box boundaries for the given (r,g,b)-triplet. Each box
+ covers eight cache slots (32 colour values, that is). */
+
+ r0 = r & 0xe0; r1 = r0 + 0x1f; rc = (r0 + r1) / 2;
+ g0 = g & 0xe0; g1 = g0 + 0x1f; gc = (g0 + g1) / 2;
+ b0 = b & 0xe0; b1 = b0 + 0x1f; bc = (b0 + b1) / 2;
+
+ /* Step 1 -- Select relevant palette entries (after Heckbert) */
+
+ /* For each palette entry, calculate the min and max distances to
+ * any position in the box given by the colour we're looking for. */
+
+ dmax = (unsigned int) ~0;
+
+ for (i = 0; i < 256; i++) {
+
+ int r, g, b;
+ unsigned int tmin, tmax;
+
+ /* Find min and max distances to any point in the box */
+ r = palette->palette[i*4+0];
+ tmin = (r < r0) ? RDIST(r, r1) : (r > r1) ? RDIST(r, r0) : 0;
+ tmax = (r <= rc) ? RDIST(r, r1) : RDIST(r, r0);
+
+ g = palette->palette[i*4+1];
+ tmin += (g < g0) ? GDIST(g, g1) : (g > g1) ? GDIST(g, g0) : 0;
+ tmax += (g <= gc) ? GDIST(g, g1) : GDIST(g, g0);
+
+ b = palette->palette[i*4+2];
+ tmin += (b < b0) ? BDIST(b, b1) : (b > b1) ? BDIST(b, b0) : 0;
+ tmax += (b <= bc) ? BDIST(b, b1) : BDIST(b, b0);
+
+ dmin[i] = tmin;
+ if (tmax < dmax)
+ dmax = tmax; /* keep the smallest max distance only */
+
+ }
+
+ /* Step 2 -- Incrementally update cache slot (after Thomas) */
+
+ /* Find the box containing the nearest palette entry, and update
+ * all slots in that box. We only check boxes for which the min
+ * distance is less than or equal the smallest max distance */
+
+ for (i = 0; i < BOXVOLUME; i++)
+ d[i] = (unsigned int) ~0;
+
+ for (i = 0; i < 256; i++)
+
+ if (dmin[i] <= dmax) {
+
+ int rd, gd, bd;
+ int ri, gi, bi;
+ int rx, gx, bx;
+
+ ri = (r0 - palette->palette[i*4+0]) * RSCALE;
+ gi = (g0 - palette->palette[i*4+1]) * GSCALE;
+ bi = (b0 - palette->palette[i*4+2]) * BSCALE;
+
+ rd = ri*ri + gi*gi + bi*bi;
+
+ ri = ri * (2 * RSTEP) + RSTEP * RSTEP;
+ gi = gi * (2 * GSTEP) + GSTEP * GSTEP;
+ bi = bi * (2 * BSTEP) + BSTEP * BSTEP;
+
+ rx = ri;
+ for (r = j = 0; r < BOX; r++) {
+ gd = rd; gx = gi;
+ for (g = 0; g < BOX; g++) {
+ bd = gd; bx = bi;
+ for (b = 0; b < BOX; b++) {
+ if ((unsigned int) bd < d[j]) {
+ d[j] = bd;
+ c[j] = (UINT8) i;
+ }
+ bd += bx;
+ bx += 2 * BSTEP * BSTEP;
+ j++;
+ }
+ gd += gx;
+ gx += 2 * GSTEP * GSTEP;
+ }
+ rd += rx;
+ rx += 2 * RSTEP * RSTEP;
+ }
+ }
+
+ /* Step 3 -- Update cache */
+
+ /* The c array now contains the closest match for each
+ * cache slot in the box. Update the cache. */
+
+ j = 0;
+ for (r = r0; r < r1; r+=4)
+ for (g = g0; g < g1; g+=4)
+ for (b = b0; b < b1; b+=4)
+ ImagingPaletteCache(palette, r, g, b) = c[j++];
+}
+
+
+int
+ImagingPaletteCachePrepare(ImagingPalette palette)
+{
+ /* Add a colour cache to a palette */
+
+ int i;
+ int entries = 64*64*64;
+
+ if (palette->cache == NULL) {
+
+ /* The cache is 512k. It might be a good idea to break it
+ up into a pointer array (e.g. an 8-bit image?) */
+
+ palette->cache = (INT16*) malloc(entries * sizeof(INT16));
+ if (!palette->cache) {
+ ImagingError_MemoryError();
+ return -1;
+ }
+
+ /* Mark all entries as empty */
+ for (i = 0; i < entries; i++)
+ palette->cache[i] = 0x100;
+
+ }
+
+ return 0;
+}
+
+
+void
+ImagingPaletteCacheDelete(ImagingPalette palette)
+{
+ /* Release the colour cache, if any */
+
+ if (palette && palette->cache) {
+ free(palette->cache);
+ palette->cache = NULL;
+ }
+}
diff --git a/Imaging/libImaging/Paste.c b/Imaging/libImaging/Paste.c
new file mode 100644
index 0000000..51a343b
--- /dev/null
+++ b/Imaging/libImaging/Paste.c
@@ -0,0 +1,555 @@
+/*
+ * The Python Imaging Library
+ * $Id: Paste.c 2409 2005-05-15 09:41:24Z Fredrik $
+ *
+ * paste image on another image
+ *
+ * history:
+ * 96-03-27 fl Created
+ * 96-07-16 fl Support "1", "L" and "RGBA" masks
+ * 96-08-16 fl Merged with opaque paste
+ * 97-01-17 fl Faster blending, added support for RGBa images
+ * 97-08-27 fl Faster masking for 32-bit images
+ * 98-02-02 fl Fixed MULDIV255 macro for gcc
+ * 99-02-02 fl Added "RGBa" mask support
+ * 99-02-06 fl Rewritten. Added support for masked fill operations.
+ * 99-12-08 fl Fixed matte fill.
+ *
+ * Copyright (c) Fredrik Lundh 1996-97.
+ * Copyright (c) Secret Labs AB 1997-99.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+#include "Imaging.h"
+
+/* like (a * b + 127) / 255), but much faster on most platforms */
+#define MULDIV255NEW(a, b, tmp)\
+ (tmp = (a) * (b) + 128, ((((tmp) >> 8) + (tmp)) >> 8))
+
+#define MULDIV255OLD(a, b, tmp)\
+ (((a) * (b) + 127) / 255)
+
+#define MULDIV255 MULDIV255NEW
+
+#define BLEND(mask, in1, in2, tmp1, tmp2)\
+ (MULDIV255(in1, 255 - mask, tmp1) + MULDIV255(in2, mask, tmp2))
+
+#define PREBLEND(mask, in1, in2, tmp1)\
+ (MULDIV255(in1, 255 - mask, tmp1) + in2)
+
+static inline void
+paste(Imaging imOut, Imaging imIn, int dx, int dy, int sx, int sy,
+ int xsize, int ysize, int pixelsize)
+{
+ /* paste opaque region */
+
+ int y;
+
+ dx *= pixelsize;
+ sx *= pixelsize;
+
+ xsize *= pixelsize;
+
+ for (y = 0; y < ysize; y++)
+ memcpy(imOut->image[y+dy]+dx, imIn->image[y+sy]+sx, xsize);
+}
+
+static inline void
+paste_mask_1(Imaging imOut, Imaging imIn, Imaging imMask,
+ int dx, int dy, int sx, int sy,
+ int xsize, int ysize, int pixelsize)
+{
+ /* paste with mode "1" mask */
+
+ int x, y;
+
+ if (imOut->image8) {
+
+ for (y = 0; y < ysize; y++) {
+ UINT8* out = imOut->image8[y+dy]+dx;
+ UINT8* in = imIn->image8[y+sy]+sx;
+ UINT8* mask = imMask->image8[y+sy]+sx;
+ for (x = 0; x < xsize; x++) {
+ if (*mask++)
+ *out = *in;
+ out++, in++;
+ }
+ }
+
+ } else {
+
+ for (y = 0; y < ysize; y++) {
+ INT32* out = imOut->image32[y+dy]+dx;
+ INT32* in = imIn->image32[y+sy]+sx;
+ UINT8* mask = imMask->image8[y+sy]+sx;
+ for (x = 0; x < xsize; x++) {
+ if (*mask++)
+ *out = *in;
+ out++, in++;
+ }
+ }
+ }
+}
+
+static inline void
+paste_mask_L(Imaging imOut, Imaging imIn, Imaging imMask,
+ int dx, int dy, int sx, int sy,
+ int xsize, int ysize, int pixelsize)
+{
+ /* paste with mode "L" matte */
+
+ int x, y, i;
+ unsigned int tmp1, tmp2;
+
+ if (imOut->image8) {
+
+ for (y = 0; y < ysize; y++) {
+ UINT8* out = imOut->image8[y+dy]+dx;
+ UINT8* in = imIn->image8[y+sy]+sx;
+ UINT8* mask = imMask->image8[y+sy]+sx;
+ for (x = 0; x < xsize; x++) {
+ *out = BLEND(*mask, *out, *in, tmp1, tmp2);
+ out++, in++, mask++;
+ }
+ }
+
+ } else {
+
+ for (y = 0; y < ysize; y++) {
+ UINT8* out = (UINT8*) imOut->image[y+dy]+dx*pixelsize;
+ UINT8* in = (UINT8*) imIn->image[y+sy]+sx*pixelsize;
+ UINT8* mask = (UINT8*) imMask->image[y+sy]+sx;
+ for (x = 0; x < xsize; x++) {
+ for (i = 0; i < pixelsize; i++) {
+ *out = BLEND(*mask, *out, *in, tmp1, tmp2);
+ out++, in++;
+ }
+ mask++;
+ }
+ }
+ }
+}
+
+static inline void
+paste_mask_RGBA(Imaging imOut, Imaging imIn, Imaging imMask,
+ int dx, int dy, int sx, int sy,
+ int xsize, int ysize, int pixelsize)
+{
+ /* paste with mode "RGBA" matte */
+
+ int x, y, i;
+ unsigned int tmp1, tmp2;
+
+ if (imOut->image8) {
+
+ for (y = 0; y < ysize; y++) {
+ UINT8* out = imOut->image8[y+dy]+dx;
+ UINT8* in = imIn->image8[y+sy]+sx;
+ UINT8* mask = (UINT8*) imMask->image[y+sy]+sx*4+3;
+ for (x = 0; x < xsize; x++) {
+ *out = BLEND(*mask, *out, *in, tmp1, tmp2);
+ out++, in++, mask += 4;
+ }
+ }
+
+ } else {
+
+ for (y = 0; y < ysize; y++) {
+ UINT8* out = (UINT8*) imOut->image[y+dy]+dx*pixelsize;
+ UINT8* in = (UINT8*) imIn->image[y+sy]+sx*pixelsize;
+ UINT8* mask = (UINT8*) imMask->image[y+sy]+sx*4+3;
+ for (x = 0; x < xsize; x++) {
+ for (i = 0; i < pixelsize; i++) {
+ *out = BLEND(*mask, *out, *in, tmp1, tmp2);
+ out++, in++;
+ }
+ mask += 4;
+ }
+ }
+ }
+}
+
+
+static inline void
+paste_mask_RGBa(Imaging imOut, Imaging imIn, Imaging imMask,
+ int dx, int dy, int sx, int sy,
+ int xsize, int ysize, int pixelsize)
+{
+ /* paste with mode "RGBa" matte */
+
+ int x, y, i;
+ unsigned int tmp1;
+
+ if (imOut->image8) {
+
+ for (y = 0; y < ysize; y++) {
+ UINT8* out = imOut->image8[y+dy]+dx;
+ UINT8* in = imIn->image8[y+sy]+sx;
+ UINT8* mask = (UINT8*) imMask->image[y+sy]+sx*4+3;
+ for (x = 0; x < xsize; x++) {
+ *out = PREBLEND(*mask, *out, *in, tmp1);
+ out++, in++, mask += 4;
+ }
+ }
+
+ } else {
+
+ for (y = 0; y < ysize; y++) {
+ UINT8* out = (UINT8*) imOut->image[y+dy]+dx*pixelsize;
+ UINT8* in = (UINT8*) imIn->image[y+sy]+sx*pixelsize;
+ UINT8* mask = (UINT8*) imMask->image[y+sy]+sx*4+3;
+ for (x = 0; x < xsize; x++) {
+ for (i = 0; i < pixelsize; i++) {
+ *out = PREBLEND(*mask, *out, *in, tmp1);
+ out++, in++;
+ }
+ mask += 4;
+ }
+ }
+ }
+}
+
+int
+ImagingPaste(Imaging imOut, Imaging imIn, Imaging imMask,
+ int dx0, int dy0, int dx1, int dy1)
+{
+ int xsize, ysize;
+ int pixelsize;
+ int sx0, sy0;
+ ImagingSectionCookie cookie;
+
+ if (!imOut || !imIn) {
+ ImagingError_ModeError();
+ return -1;
+ }
+
+ pixelsize = imOut->pixelsize;
+
+ xsize = dx1 - dx0;
+ ysize = dy1 - dy0;
+
+ if (xsize != imIn->xsize || ysize != imIn->ysize ||
+ pixelsize != imIn->pixelsize) {
+ ImagingError_Mismatch();
+ return -1;
+ }
+
+ if (imMask && (xsize != imMask->xsize || ysize != imMask->ysize)) {
+ ImagingError_Mismatch();
+ return -1;
+ }
+
+ /* Determine which region to copy */
+ sx0 = sy0 = 0;
+ if (dx0 < 0)
+ xsize += dx0, sx0 = -dx0, dx0 = 0;
+ if (dx0 + xsize > imOut->xsize)
+ xsize = imOut->xsize - dx0;
+ if (dy0 < 0)
+ ysize += dy0, sy0 = -dy0, dy0 = 0;
+ if (dy0 + ysize > imOut->ysize)
+ ysize = imOut->ysize - dy0;
+
+ if (xsize <= 0 || ysize <= 0)
+ return 0;
+
+ if (!imMask) {
+ ImagingSectionEnter(&cookie);
+ paste(imOut, imIn, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
+ ImagingSectionLeave(&cookie);
+
+ } else if (strcmp(imMask->mode, "1") == 0) {
+ ImagingSectionEnter(&cookie);
+ paste_mask_1(imOut, imIn, imMask, dx0, dy0, sx0, sy0,
+ xsize, ysize, pixelsize);
+ ImagingSectionLeave(&cookie);
+
+ } else if (strcmp(imMask->mode, "L") == 0) {
+ ImagingSectionEnter(&cookie);
+ paste_mask_L(imOut, imIn, imMask, dx0, dy0, sx0, sy0,
+ xsize, ysize, pixelsize);
+ ImagingSectionLeave(&cookie);
+
+ } else if (strcmp(imMask->mode, "RGBA") == 0) {
+ ImagingSectionEnter(&cookie);
+ paste_mask_RGBA(imOut, imIn, imMask, dx0, dy0, sx0, sy0,
+ xsize, ysize, pixelsize);
+ ImagingSectionLeave(&cookie);
+
+ } else if (strcmp(imMask->mode, "RGBa") == 0) {
+ ImagingSectionEnter(&cookie);
+ paste_mask_RGBa(imOut, imIn, imMask, dx0, dy0, sx0, sy0,
+ xsize, ysize, pixelsize);
+ ImagingSectionLeave(&cookie);
+
+ } else {
+ ImagingError_ValueError("bad transparency mask");
+ return -1;
+ }
+
+ return 0;
+}
+
+static inline void
+fill(Imaging imOut, const void* ink_, int dx, int dy,
+ int xsize, int ysize, int pixelsize)
+{
+ /* fill opaque region */
+
+ int x, y;
+ UINT8 ink8 = 0;
+ INT32 ink32 = 0L;
+
+ memcpy(&ink32, ink_, pixelsize);
+ memcpy(&ink8, ink_, sizeof(ink8));
+
+ if (imOut->image8 || ink32 == 0L) {
+
+ dx *= pixelsize;
+ xsize *= pixelsize;
+ for (y = 0; y < ysize; y++)
+ memset(imOut->image[y+dy]+dx, ink8, xsize);
+
+ } else {
+
+ for (y = 0; y < ysize; y++) {
+ INT32* out = imOut->image32[y+dy]+dx;
+ for (x = 0; x < xsize; x++)
+ out[x] = ink32;
+ }
+
+ }
+}
+
+static inline void
+fill_mask_1(Imaging imOut, const void* ink_, Imaging imMask,
+ int dx, int dy, int sx, int sy,
+ int xsize, int ysize, int pixelsize)
+{
+ /* fill with mode "1" mask */
+
+ int x, y;
+ UINT8 ink8 = 0;
+ INT32 ink32 = 0L;
+
+ memcpy(&ink32, ink_, pixelsize);
+ memcpy(&ink8, ink_, sizeof(ink8));
+
+ if (imOut->image8) {
+
+ for (y = 0; y < ysize; y++) {
+ UINT8* out = imOut->image8[y+dy]+dx;
+ UINT8* mask = imMask->image8[y+sy]+sx;
+ for (x = 0; x < xsize; x++) {
+ if (*mask++)
+ *out = ink8;
+ out++;
+ }
+ }
+
+ } else {
+
+ for (y = 0; y < ysize; y++) {
+ INT32* out = imOut->image32[y+dy]+dx;
+ UINT8* mask = imMask->image8[y+sy]+sx;
+ for (x = 0; x < xsize; x++) {
+ if (*mask++)
+ *out = ink32;
+ out++;
+ }
+ }
+ }
+}
+
+static inline void
+fill_mask_L(Imaging imOut, const UINT8* ink, Imaging imMask,
+ int dx, int dy, int sx, int sy,
+ int xsize, int ysize, int pixelsize)
+{
+ /* fill with mode "L" matte */
+
+ int x, y, i;
+ unsigned int tmp1, tmp2;
+
+ if (imOut->image8) {
+
+ for (y = 0; y < ysize; y++) {
+ UINT8* out = imOut->image8[y+dy]+dx;
+ UINT8* mask = imMask->image8[y+sy]+sx;
+ for (x = 0; x < xsize; x++) {
+ *out = BLEND(*mask, *out, ink[0], tmp1, tmp2);
+ out++, mask++;
+ }
+ }
+
+ } else {
+
+ for (y = 0; y < ysize; y++) {
+ UINT8* out = (UINT8*) imOut->image[y+dy]+dx*pixelsize;
+ UINT8* mask = (UINT8*) imMask->image[y+sy]+sx;
+ for (x = 0; x < xsize; x++) {
+ for (i = 0; i < pixelsize; i++) {
+ *out = BLEND(*mask, *out, ink[i], tmp1, tmp2);
+ out++;
+ }
+ mask++;
+ }
+ }
+ }
+}
+
+static inline void
+fill_mask_RGBA(Imaging imOut, const UINT8* ink, Imaging imMask,
+ int dx, int dy, int sx, int sy,
+ int xsize, int ysize, int pixelsize)
+{
+ /* fill with mode "RGBA" matte */
+
+ int x, y, i;
+ unsigned int tmp1, tmp2;
+
+ if (imOut->image8) {
+
+ sx = sx*4+3;
+ for (y = 0; y < ysize; y++) {
+ UINT8* out = imOut->image8[y+dy]+dx;
+ UINT8* mask = (UINT8*) imMask->image[y+sy]+sx;
+ for (x = 0; x < xsize; x++) {
+ *out = BLEND(*mask, *out, ink[0], tmp1, tmp2);
+ out++, mask += 4;
+ }
+ }
+
+ } else {
+
+ dx *= pixelsize;
+ sx = sx*4 + 3;
+ for (y = 0; y < ysize; y++) {
+ UINT8* out = (UINT8*) imOut->image[y+dy]+dx;
+ UINT8* mask = (UINT8*) imMask->image[y+sy]+sx;
+ for (x = 0; x < xsize; x++) {
+ for (i = 0; i < pixelsize; i++) {
+ *out = BLEND(*mask, *out, ink[i], tmp1, tmp2);
+ out++;
+ }
+ mask += 4;
+ }
+ }
+ }
+}
+
+static inline void
+fill_mask_RGBa(Imaging imOut, const UINT8* ink, Imaging imMask,
+ int dx, int dy, int sx, int sy,
+ int xsize, int ysize, int pixelsize)
+{
+ /* fill with mode "RGBa" matte */
+
+ int x, y, i;
+ unsigned int tmp1;
+
+ if (imOut->image8) {
+
+ sx = sx*4 + 3;
+ for (y = 0; y < ysize; y++) {
+ UINT8* out = imOut->image8[y+dy]+dx;
+ UINT8* mask = (UINT8*) imMask->image[y+sy]+sx;
+ for (x = 0; x < xsize; x++) {
+ *out = PREBLEND(*mask, *out, ink[0], tmp1);
+ out++, mask += 4;
+ }
+ }
+
+ } else {
+
+ dx *= pixelsize;
+ sx = sx*4 + 3;
+ for (y = 0; y < ysize; y++) {
+ UINT8* out = (UINT8*) imOut->image[y+dy]+dx;
+ UINT8* mask = (UINT8*) imMask->image[y+sy]+sx;
+ for (x = 0; x < xsize; x++) {
+ for (i = 0; i < pixelsize; i++) {
+ *out = PREBLEND(*mask, *out, ink[i], tmp1);
+ out++;
+ }
+ mask += 4;
+ }
+ }
+ }
+}
+
+int
+ImagingFill2(Imaging imOut, const void* ink, Imaging imMask,
+ int dx0, int dy0, int dx1, int dy1)
+{
+ ImagingSectionCookie cookie;
+ int xsize, ysize;
+ int pixelsize;
+ int sx0, sy0;
+
+ if (!imOut || !ink) {
+ ImagingError_ModeError();
+ return -1;
+ }
+
+ pixelsize = imOut->pixelsize;
+
+ xsize = dx1 - dx0;
+ ysize = dy1 - dy0;
+
+ if (imMask && (xsize != imMask->xsize || ysize != imMask->ysize)) {
+ ImagingError_Mismatch();
+ return -1;
+ }
+
+ /* Determine which region to fill */
+ sx0 = sy0 = 0;
+ if (dx0 < 0)
+ xsize += dx0, sx0 = -dx0, dx0 = 0;
+ if (dx0 + xsize > imOut->xsize)
+ xsize = imOut->xsize - dx0;
+ if (dy0 < 0)
+ ysize += dy0, sy0 = -dy0, dy0 = 0;
+ if (dy0 + ysize > imOut->ysize)
+ ysize = imOut->ysize - dy0;
+
+ if (xsize <= 0 || ysize <= 0)
+ return 0;
+
+ if (!imMask) {
+ ImagingSectionEnter(&cookie);
+ fill(imOut, ink, dx0, dy0, xsize, ysize, pixelsize);
+ ImagingSectionLeave(&cookie);
+
+ } else if (strcmp(imMask->mode, "1") == 0) {
+ ImagingSectionEnter(&cookie);
+ fill_mask_1(imOut, ink, imMask, dx0, dy0, sx0, sy0,
+ xsize, ysize, pixelsize);
+ ImagingSectionLeave(&cookie);
+
+ } else if (strcmp(imMask->mode, "L") == 0) {
+ ImagingSectionEnter(&cookie);
+ fill_mask_L(imOut, ink, imMask, dx0, dy0, sx0, sy0,
+ xsize, ysize, pixelsize);
+ ImagingSectionLeave(&cookie);
+
+ } else if (strcmp(imMask->mode, "RGBA") == 0) {
+ ImagingSectionEnter(&cookie);
+ fill_mask_RGBA(imOut, ink, imMask, dx0, dy0, sx0, sy0,
+ xsize, ysize, pixelsize);
+ ImagingSectionLeave(&cookie);
+
+ } else if (strcmp(imMask->mode, "RGBa") == 0) {
+ ImagingSectionEnter(&cookie);
+ fill_mask_RGBa(imOut, ink, imMask, dx0, dy0, sx0, sy0,
+ xsize, ysize, pixelsize);
+ ImagingSectionLeave(&cookie);
+
+ } else {
+ ImagingError_ValueError("bad transparency mask");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/Imaging/libImaging/PcdDecode.c b/Imaging/libImaging/PcdDecode.c
new file mode 100644
index 0000000..6faab3b
--- /dev/null
+++ b/Imaging/libImaging/PcdDecode.c
@@ -0,0 +1,78 @@
+/*
+ * The Python Imaging Library.
+ * $Id: PcdDecode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * decoder for uncompressed PCD image data.
+ *
+ * history:
+ * 96-05-10 fl Created
+ * 96-05-18 fl New tables
+ * 97-01-25 fl Use PhotoYCC unpacker
+ *
+ * notes:
+ * This driver supports uncompressed PCD modes only
+ * (resolutions up to 768x512).
+ *
+ * Copyright (c) Fredrik Lundh 1996-97.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+int
+ImagingPcdDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ int x;
+ int chunk;
+ UINT8* out;
+ UINT8* ptr;
+
+ ptr = buf;
+
+ chunk = 3 * state->xsize;
+
+ for (;;) {
+
+ /* We need data for two full lines before we can do anything */
+ if (bytes < chunk)
+ return ptr - buf;
+
+ /* Unpack first line */
+ out = state->buffer;
+ for (x = 0; x < state->xsize; x++) {
+ out[0] = ptr[x];
+ out[1] = ptr[(x+4*state->xsize)/2];
+ out[2] = ptr[(x+5*state->xsize)/2];
+ out += 4;
+ }
+
+ state->shuffle((UINT8*) im->image[state->y],
+ state->buffer, state->xsize);
+
+ if (++state->y >= state->ysize)
+ return -1; /* This can hardly happen */
+
+ /* Unpack second line */
+ out = state->buffer;
+ for (x = 0; x < state->xsize; x++) {
+ out[0] = ptr[x+state->xsize];
+ out[1] = ptr[(x+4*state->xsize)/2];
+ out[2] = ptr[(x+5*state->xsize)/2];
+ out += 4;
+ }
+
+ state->shuffle((UINT8*) im->image[state->y],
+ state->buffer, state->xsize);
+
+ if (++state->y >= state->ysize)
+ return -1;
+
+ ptr += chunk;
+ bytes -= chunk;
+
+ }
+}
diff --git a/Imaging/libImaging/PcxDecode.c b/Imaging/libImaging/PcxDecode.c
new file mode 100644
index 0000000..7267f30
--- /dev/null
+++ b/Imaging/libImaging/PcxDecode.c
@@ -0,0 +1,75 @@
+/*
+ * The Python Imaging Library.
+ * $Id: PcxDecode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * decoder for PCX image data.
+ *
+ * history:
+ * 95-09-14 fl Created
+ *
+ * Copyright (c) Fredrik Lundh 1995.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+int
+ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ UINT8 n;
+ UINT8* ptr;
+
+ ptr = buf;
+
+ for (;;) {
+
+ if (bytes < 1)
+ return ptr - buf;
+
+ if ((*ptr & 0xC0) == 0xC0) {
+
+ /* Run */
+ if (bytes < 2)
+ return ptr - buf;
+
+ n = ptr[0] & 0x3F;
+
+ while (n > 0) {
+ if (state->x >= state->bytes) {
+ state->errcode = IMAGING_CODEC_OVERRUN;
+ break;
+ }
+ state->buffer[state->x++] = ptr[1];
+ n--;
+ }
+
+ ptr += 2; bytes -= 2;
+
+ } else {
+
+ /* Literal */
+ state->buffer[state->x++] = ptr[0];
+ ptr++; bytes--;
+
+ }
+
+ if (state->x >= state->bytes) {
+
+ /* Got a full line, unpack it */
+ state->shuffle((UINT8*) im->image[state->y + state->yoff] +
+ state->xoff * im->pixelsize, state->buffer,
+ state->xsize);
+
+ state->x = 0;
+
+ if (++state->y >= state->ysize) {
+ /* End of file (errcode = 0) */
+ return -1;
+ }
+ }
+
+ }
+}
diff --git a/Imaging/libImaging/PcxEncode.c b/Imaging/libImaging/PcxEncode.c
new file mode 100644
index 0000000..2c9d250
--- /dev/null
+++ b/Imaging/libImaging/PcxEncode.c
@@ -0,0 +1,148 @@
+/*
+ * The Python Imaging Library.
+ * $Id: PcxEncode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * encoder for PCX data
+ *
+ * history:
+ * 99-02-07 fl created
+ *
+ * Copyright (c) Fredrik Lundh 1999.
+ * Copyright (c) Secret Labs AB 1999.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+enum { INIT, FETCH, ENCODE };
+
+/* we're reusing "ystep" to store the last value */
+#define LAST ystep
+
+int
+ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ UINT8* ptr;
+ int this;
+
+ ptr = buf;
+
+ if (!state->state) {
+
+ /* sanity check */
+ if (state->xsize <= 0 || state->ysize <= 0) {
+ state->errcode = IMAGING_CODEC_END;
+ return 0;
+ }
+
+ state->bytes = (state->xsize*state->bits + 7) / 8;
+ state->state = FETCH;
+
+ }
+
+ for (;;)
+
+ switch (state->state) {
+ case FETCH:
+
+ /* get a line of data */
+ if (state->y >= state->ysize) {
+ state->errcode = IMAGING_CODEC_END;
+ return ptr - buf;
+ }
+
+ state->shuffle(state->buffer,
+ (UINT8*) im->image[state->y + state->yoff] +
+ state->xoff * im->pixelsize, state->xsize);
+
+ state->y++;
+
+ state->count = 1;
+ state->LAST = state->buffer[0];
+
+ state->x = 1;
+
+ state->state = ENCODE;
+ /* fall through */
+
+ case ENCODE:
+
+ /* compress this line */
+
+ /* when we arrive here, "count" contains the number of
+ bytes having the value of "LAST" that we've already
+ seen */
+
+ while (state->x < state->bytes) {
+
+ if (state->count == 63) {
+
+ /* this run is full; flush it */
+ if (bytes < 2)
+ return ptr - buf;
+ *ptr++ = 0xff;
+ *ptr++ = state->LAST;
+ bytes -= 2;
+
+ state->count = 0;
+
+ }
+
+ this = state->buffer[state->x];
+
+ if (this == state->LAST) {
+
+ /* extend the current run */
+ state->x++;
+ state->count++;
+
+ } else {
+
+ /* start a new run */
+ if (state->count == 1 && (state->LAST < 0xc0)) {
+ if (bytes < 1)
+ return ptr - buf;
+ *ptr++ = state->LAST;
+ bytes--;
+ } else {
+ if (state->count > 0) {
+ if (bytes < 2)
+ return ptr - buf;
+ *ptr++ = 0xc0 | state->count;
+ *ptr++ = state->LAST;
+ bytes -= 2;
+ }
+ }
+
+ state->LAST = this;
+ state->count = 1;
+
+ state->x++;
+
+ }
+ }
+
+ /* end of line; flush the current run */
+ if (state->count == 1 && (state->LAST < 0xc0)) {
+ if (bytes < 1)
+ return ptr - buf;
+ *ptr++ = state->LAST;
+ bytes--;
+ } else {
+ if (state->count > 0) {
+ if (bytes < 2)
+ return ptr - buf;
+ *ptr++ = 0xc0 | state->count;
+ *ptr++ = state->LAST;
+ bytes -= 2;
+ }
+ }
+
+ /* read next line */
+ state->state = FETCH;
+ break;
+
+ }
+}
diff --git a/Imaging/libImaging/Point.c b/Imaging/libImaging/Point.c
new file mode 100644
index 0000000..45693f0
--- /dev/null
+++ b/Imaging/libImaging/Point.c
@@ -0,0 +1,263 @@
+/*
+ * The Python Imaging Library
+ * $Id: Point.c 2207 2004-12-19 15:06:45Z fredrik $
+ *
+ * point (pixel) translation
+ *
+ * history:
+ * 1995-11-27 fl Created
+ * 1996-03-31 fl Fixed colour support
+ * 1996-08-13 fl Support 8-bit to "1" thresholding
+ * 1997-05-31 fl Added floating point transform
+ * 1998-07-02 fl Added integer point transform
+ * 1998-07-17 fl Support L to anything lookup
+ * 2004-12-18 fl Refactored; added I to L lookup
+ *
+ * Copyright (c) 1997-2004 by Secret Labs AB.
+ * Copyright (c) 1995-2004 by Fredrik Lundh.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+typedef struct {
+ const void* table;
+} im_point_context;
+
+static void
+im_point_8_8(Imaging imOut, Imaging imIn, im_point_context* context)
+{
+ int x, y;
+ /* 8-bit source, 8-bit destination */
+ UINT8* table = (UINT8*) context->table;
+ for (y = 0; y < imIn->ysize; y++) {
+ UINT8* in = imIn->image8[y];
+ UINT8* out = imOut->image8[y];
+ for (x = 0; x < imIn->xsize; x++)
+ out[x] = table[in[x]];
+ }
+}
+
+static void
+im_point_2x8_2x8(Imaging imOut, Imaging imIn, im_point_context* context)
+{
+ int x, y;
+ /* 2x8-bit source, 2x8-bit destination */
+ UINT8* table = (UINT8*) context->table;
+ for (y = 0; y < imIn->ysize; y++) {
+ UINT8* in = (UINT8*) imIn->image[y];
+ UINT8* out = (UINT8*) imOut->image[y];
+ for (x = 0; x < imIn->xsize; x++) {
+ out[0] = table[in[0]];
+ out[3] = table[in[3]+256];
+ in += 4; out += 4;
+ }
+ }
+}
+
+static void
+im_point_3x8_3x8(Imaging imOut, Imaging imIn, im_point_context* context)
+{
+ int x, y;
+ /* 3x8-bit source, 3x8-bit destination */
+ UINT8* table = (UINT8*) context->table;
+ for (y = 0; y < imIn->ysize; y++) {
+ UINT8* in = (UINT8*) imIn->image[y];
+ UINT8* out = (UINT8*) imOut->image[y];
+ for (x = 0; x < imIn->xsize; x++) {
+ out[0] = table[in[0]];
+ out[1] = table[in[1]+256];
+ out[2] = table[in[2]+512];
+ in += 4; out += 4;
+ }
+ }
+}
+
+static void
+im_point_4x8_4x8(Imaging imOut, Imaging imIn, im_point_context* context)
+{
+ int x, y;
+ /* 4x8-bit source, 4x8-bit destination */
+ UINT8* table = (UINT8*) context->table;
+ for (y = 0; y < imIn->ysize; y++) {
+ UINT8* in = (UINT8*) imIn->image[y];
+ UINT8* out = (UINT8*) imOut->image[y];
+ for (x = 0; x < imIn->xsize; x++) {
+ out[0] = table[in[0]];
+ out[1] = table[in[1]+256];
+ out[2] = table[in[2]+512];
+ out[3] = table[in[3]+768];
+ in += 4; out += 4;
+ }
+ }
+}
+
+static void
+im_point_8_32(Imaging imOut, Imaging imIn, im_point_context* context)
+{
+ int x, y;
+ /* 8-bit source, 32-bit destination */
+ INT32* table = (INT32*) context->table;
+ for (y = 0; y < imIn->ysize; y++) {
+ UINT8* in = imIn->image8[y];
+ INT32* out = imOut->image32[y];
+ for (x = 0; x < imIn->xsize; x++)
+ out[x] = table[in[x]];
+ }
+}
+
+static void
+im_point_32_8(Imaging imOut, Imaging imIn, im_point_context* context)
+{
+ int x, y;
+ /* 32-bit source, 8-bit destination */
+ UINT8* table = (UINT8*) context->table;
+ for (y = 0; y < imIn->ysize; y++) {
+ INT32* in = imIn->image32[y];
+ UINT8* out = imOut->image8[y];
+ for (x = 0; x < imIn->xsize; x++) {
+ int v = in[x];
+ if (v < 0)
+ v = 0;
+ else if (v > 65535)
+ v = 65535;
+ out[x] = table[v];
+ }
+ }
+}
+
+Imaging
+ImagingPoint(Imaging imIn, const char* mode, const void* table)
+{
+ /* lookup table transform */
+
+ ImagingSectionCookie cookie;
+ Imaging imOut;
+ im_point_context context;
+ void (*point)(Imaging imIn, Imaging imOut, im_point_context* context);
+
+ if (!imIn)
+ return (Imaging) ImagingError_ModeError();
+
+ if (!mode)
+ mode = imIn->mode;
+
+ if (imIn->type != IMAGING_TYPE_UINT8) {
+ if (imIn->type != IMAGING_TYPE_INT32 || strcmp(mode, "L") != 0)
+ goto mode_mismatch;
+ } else if (!imIn->image8 && strcmp(imIn->mode, mode) != 0)
+ goto mode_mismatch;
+
+ imOut = ImagingNew(mode, imIn->xsize, imIn->ysize);
+ if (!imOut)
+ return NULL;
+
+ /* find appropriate handler */
+ if (imIn->type == IMAGING_TYPE_UINT8) {
+ if (imIn->bands == imOut->bands && imIn->type == imOut->type) {
+ switch (imIn->bands) {
+ case 1:
+ point = im_point_8_8;
+ break;
+ case 2:
+ point = im_point_2x8_2x8;
+ break;
+ case 3:
+ point = im_point_3x8_3x8;
+ break;
+ case 4:
+ point = im_point_4x8_4x8;
+ break;
+ default:
+ /* this cannot really happen */
+ point = im_point_8_8;
+ break;
+ }
+ } else
+ point = im_point_8_32;
+ } else
+ point = im_point_32_8;
+
+ ImagingCopyInfo(imOut, imIn);
+
+ ImagingSectionEnter(&cookie);
+
+ context.table = table;
+ point(imOut, imIn, &context);
+
+ ImagingSectionLeave(&cookie);
+
+ return imOut;
+
+ mode_mismatch:
+ return (Imaging) ImagingError_ValueError(
+ "point operation not supported for this mode"
+ );
+}
+
+
+Imaging
+ImagingPointTransform(Imaging imIn, double scale, double offset)
+{
+ /* scale/offset transform */
+
+ ImagingSectionCookie cookie;
+ Imaging imOut;
+ int x, y;
+
+ if (!imIn || (strcmp(imIn->mode, "I") != 0 &&
+ strcmp(imIn->mode, "I;16") != 0 &&
+ strcmp(imIn->mode, "F") != 0))
+ return (Imaging) ImagingError_ModeError();
+
+ imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize);
+ if (!imOut)
+ return NULL;
+
+ ImagingCopyInfo(imOut, imIn);
+
+ switch (imIn->type) {
+ case IMAGING_TYPE_INT32:
+ ImagingSectionEnter(&cookie);
+ for (y = 0; y < imIn->ysize; y++) {
+ INT32* in = imIn->image32[y];
+ INT32* out = imOut->image32[y];
+ /* FIXME: add clipping? */
+ for (x = 0; x < imIn->xsize; x++)
+ out[x] = in[x] * scale + offset;
+ }
+ ImagingSectionLeave(&cookie);
+ break;
+ case IMAGING_TYPE_FLOAT32:
+ ImagingSectionEnter(&cookie);
+ for (y = 0; y < imIn->ysize; y++) {
+ FLOAT32* in = (FLOAT32*) imIn->image32[y];
+ FLOAT32* out = (FLOAT32*) imOut->image32[y];
+ for (x = 0; x < imIn->xsize; x++)
+ out[x] = in[x] * scale + offset;
+ }
+ ImagingSectionLeave(&cookie);
+ break;
+ case IMAGING_TYPE_SPECIAL:
+ if (strcmp(imIn->mode,"I;16") == 0) {
+ ImagingSectionEnter(&cookie);
+ for (y = 0; y < imIn->ysize; y++) {
+ UINT16* in = (UINT16 *)imIn->image[y];
+ UINT16* out = (UINT16 *)imOut->image[y];
+ /* FIXME: add clipping? */
+ for (x = 0; x < imIn->xsize; x++)
+ out[x] = in[x] * scale + offset;
+ }
+ ImagingSectionLeave(&cookie);
+ break;
+ }
+ /* FALL THROUGH */
+ default:
+ ImagingDelete(imOut);
+ return (Imaging) ImagingError_ValueError("internal error");
+ }
+
+ return imOut;
+}
diff --git a/Imaging/libImaging/Quant.c b/Imaging/libImaging/Quant.c
new file mode 100644
index 0000000..66130f6
--- /dev/null
+++ b/Imaging/libImaging/Quant.c
@@ -0,0 +1,1606 @@
+/*
+ * The Python Imaging Library
+ * $Id: Quant.c 2284 2005-02-07 20:58:58Z fredrik $
+ *
+ * image quantizer
+ *
+ * history:
+ * 1998-09-10 tjs Contributed
+ * 1998-12-29 fl Added to PIL 1.0b1
+ * 2004-02-21 fl Fixed bogus free() on quantization error
+ * 2005-02-07 fl Limit number of colors to 256
+ *
+ * Written by Toby J Sargeant <tjs@longford.cs.monash.edu.au>.
+ *
+ * Copyright (c) 1998 by Toby J Sargeant
+ * Copyright (c) 1998-2004 by Secret Labs AB. All rights reserved.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+#include "Imaging.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <time.h>
+
+#include "Quant.h"
+
+#include "QuantDefines.h"
+#include "QuantHash.h"
+#include "QuantHeap.h"
+
+#define NO_OUTPUT
+
+typedef struct {
+ unsigned long scale;
+} PixelHashData;
+
+typedef struct _PixelList {
+ struct _PixelList *next[3],*prev[3];
+ Pixel p;
+ unsigned int flag:1;
+ int count;
+} PixelList;
+
+typedef struct _BoxNode {
+ struct _BoxNode *l,*r;
+ PixelList *head[3],*tail[3];
+ int axis;
+ int volume;
+ unsigned long pixelCount;
+} BoxNode;
+
+#define _SQR(x) ((x)*(x))
+#define _DISTSQR(p1,p2) \
+ _SQR((int)((p1)->c.r)-(int)((p2)->c.r))+ \
+ _SQR((int)((p1)->c.g)-(int)((p2)->c.g))+ \
+ _SQR((int)((p1)->c.b)-(int)((p2)->c.b))
+
+#define MAX_HASH_ENTRIES 65536
+
+#define PIXEL_HASH(r,g,b) \
+ (((unsigned int)(r) )*463 ^ \
+ ((unsigned int)(g)<< 8)*10069 ^ \
+ ((unsigned int)(b)<<16)*64997)
+
+#define PIXEL_UNSCALE(p,q,s) \
+ ((q)->c.r=(p)->c.r<<(s)), \
+ ((q)->c.g=(p)->c.g<<(s)), \
+ ((q)->c.b=(p)->c.b<<(s))
+
+#define PIXEL_SCALE(p,q,s)\
+ ((q)->c.r=(p)->c.r>>(s)), \
+ ((q)->c.g=(p)->c.g>>(s)), \
+ ((q)->c.b=(p)->c.b>>(s))
+
+static unsigned long
+unshifted_pixel_hash(const HashTable h, const void *p)
+{
+ Pixel *pixel=(Pixel *)&p;
+ unsigned long hash=PIXEL_HASH(pixel->c.r,
+ pixel->c.g,
+ pixel->c.b);
+ return hash;
+}
+
+static int
+unshifted_pixel_cmp(const HashTable h, const void *a, const void *b)
+{
+ Pixel *pixel1=(Pixel *)&a;
+ Pixel *pixel2=(Pixel *)&b;
+ if (pixel1->c.r==pixel2->c.r) {
+ if (pixel1->c.g==pixel2->c.g) {
+ if (pixel1->c.b==pixel2->c.b) {
+ return 0;
+ } else {
+ return (int)(pixel1->c.b)-(int)(pixel2->c.b);
+ }
+ } else {
+ return (int)(pixel1->c.g)-(int)(pixel2->c.g);
+ }
+ } else {
+ return (int)(pixel1->c.r)-(int)(pixel2->c.r);
+ }
+}
+
+static unsigned long
+pixel_hash(const HashTable h,const void *p)
+{
+ PixelHashData *d=(PixelHashData *)hashtable_get_user_data(h);
+ Pixel *pixel=(Pixel *)&p;
+ unsigned long hash=PIXEL_HASH(pixel->c.r>>d->scale,
+ pixel->c.g>>d->scale,
+ pixel->c.b>>d->scale);
+ return hash;
+}
+
+static int
+pixel_cmp(const HashTable h,const void *a,const void *b)
+{
+ PixelHashData *d=(PixelHashData *)hashtable_get_user_data(h);
+ Pixel *pixel1=(Pixel *)&a;
+ Pixel *pixel2=(Pixel *)&b;
+ unsigned long A,B;
+ A=PIXEL_HASH(pixel1->c.r>>d->scale,
+ pixel1->c.g>>d->scale,
+ pixel1->c.b>>d->scale);
+ B=PIXEL_HASH(pixel2->c.r>>d->scale,
+ pixel2->c.g>>d->scale,
+ pixel2->c.b>>d->scale);
+ return (A==B)?0:((A<B)?-1:1);
+}
+
+static void
+exists_count_func(const HashTable h, const void *key, void **val)
+{
+ (*(int *)val)+=1;
+}
+
+static void
+new_count_func(const HashTable h, const void *key, void **val)
+{
+ (*(int *)val)=1;
+}
+
+static void
+rehash_collide(HashTable h,
+ void **keyp,
+ void **valp,
+ void *newkey,
+ void *newval)
+{
+ *valp=(void *)((*(int *)valp)+(*(int *)&newval));
+}
+
+/* %% */
+
+static HashTable
+create_pixel_hash(Pixel *pixelData,unsigned long nPixels)
+{
+ PixelHashData *d;
+ HashTable *hash;
+ unsigned long i;
+ unsigned long timer,timer2,timer3;
+
+ d=malloc(sizeof(PixelHashData));
+ if (!d) return NULL;
+ hash=hashtable_new(pixel_hash,pixel_cmp);
+ hashtable_set_user_data(hash,d);
+ d->scale=0;
+ timer=timer3=clock();
+ for (i=0;i<nPixels;i++) {
+ if (!hashtable_insert_or_update_computed(hash,
+ (void *)pixelData[i].v,
+ new_count_func,
+ exists_count_func)) {;
+ }
+ while (hashtable_get_count(hash)>MAX_HASH_ENTRIES) {
+ d->scale++;
+#ifndef NO_OUTPUT
+ printf ("rehashing - new scale: %d\n",(int)d->scale);
+#endif
+ timer2=clock();
+ hashtable_rehash_compute(hash,rehash_collide);
+ timer2=clock()-timer2;
+#ifndef NO_OUTPUT
+ printf ("rehash took %f sec\n",timer2/(double)CLOCKS_PER_SEC);
+#endif
+ timer+=timer2;
+ }
+ }
+#ifndef NO_OUTPUT
+ printf ("inserts took %f sec\n",(clock()-timer)/(double)CLOCKS_PER_SEC);
+#endif
+#ifndef NO_OUTPUT
+ printf ("total %f sec\n",(clock()-timer3)/(double)CLOCKS_PER_SEC);
+#endif
+ return hash;
+}
+
+static void
+destroy_pixel_hash(HashTable hash)
+{
+ PixelHashData *d=(PixelHashData *)hashtable_get_user_data(hash);
+ if (d) free(d);
+ hashtable_free(hash);
+}
+
+
+/* 1. hash quantized pixels. */
+/* 2. create R,G,B lists of sorted quantized pixels. */
+/* 3. median cut. */
+/* 4. build hash table from median cut boxes. */
+/* 5. for each pixel, compute entry in hash table, and hence median cut box. */
+/* 6. compute median cut box pixel averages. */
+/* 7. map each pixel to nearest average. */
+
+static int
+compute_box_volume(BoxNode *b)
+{
+ unsigned char rl,rh,gl,gh,bl,bh;
+ if (b->volume>=0) return b->volume;
+ if (!b->head[0]) {
+ b->volume=0;
+ } else {
+ rh=b->head[0]->p.c.r;
+ rl=b->tail[0]->p.c.r;
+ gh=b->head[1]->p.c.g;
+ gl=b->tail[1]->p.c.g;
+ bh=b->head[2]->p.c.b;
+ bl=b->tail[2]->p.c.b;
+ b->volume=(rh-rl+1)*(gh-gl+1)*(bh-bl+1);
+ }
+ return b->volume;
+}
+
+static void
+hash_to_list(HashTable h, const void *key, const void *val, void *u)
+{
+ PixelHashData *d=(PixelHashData *)hashtable_get_user_data(h);
+ PixelList **pl=(PixelList **)u;
+ PixelList *p;
+ Pixel *pixel=(Pixel *)&key;
+ int i;
+ Pixel q;
+ int count=*(int *)&val;
+
+ PIXEL_SCALE(pixel,&q,d->scale);
+
+ p=malloc(sizeof(PixelList));
+ if (!p) return;
+
+ p->flag=0;
+ p->p=q;
+ p->count=count;
+ for (i=0;i<3;i++) {
+ p->next[i]=pl[i];
+ p->prev[i]=NULL;
+ if (pl[i]) pl[i]->prev[i]=p;
+ pl[i]=p;
+ }
+}
+
+static PixelList *
+mergesort_pixels(PixelList *head, int i)
+{
+ PixelList *c,*t,*a,*b,*p;
+ if (!head||!head->next[i]) {
+ if (head) {
+ head->next[i]=NULL;
+ head->prev[i]=NULL;
+ }
+ return head;
+ }
+ for (c=t=head;c&&t;c=c->next[i],t=(t->next[i])?t->next[i]->next[i]:NULL);
+ if (c) {
+ if (c->prev[i]) c->prev[i]->next[i]=NULL;
+ c->prev[i]=NULL;
+ }
+ a=mergesort_pixels(head,i);
+ b=mergesort_pixels(c,i);
+ head=NULL;
+ p=NULL;
+ while (a&&b) {
+ if (a->p.a.v[i]>b->p.a.v[i]) {
+ c=a;
+ a=a->next[i];
+ } else {
+ c=b;
+ b=b->next[i];
+ }
+ c->prev[i]=p;
+ c->next[i]=NULL;
+ if (p) p->next[i]=c;
+ p=c;
+ if (!head) head=c;
+ }
+ if (a) {
+ c->next[i]=a;
+ a->prev[i]=c;
+ } else if (b) {
+ c->next[i]=b;
+ b->prev[i]=c;
+ }
+ return head;
+}
+
+static int
+test_sorted(PixelList *pl[3])
+{
+ int i,n,l;
+ PixelList *t;
+
+ for(i=0;i<3;i++) {
+ n=0;
+ l=256;
+ for (t=pl[i];t;t=t->next[i]) {
+ if (l<t->p.a.v[i]) return 0;
+ l=t->p.a.v[i];
+ }
+ }
+ return 1;
+}
+
+static int
+box_heap_cmp(const Heap h, const void *A, const void *B)
+{
+ BoxNode *a=(BoxNode *)A;
+ BoxNode *b=(BoxNode *)B;
+ return (int)a->pixelCount-(int)b->pixelCount;
+}
+
+#define LUMINANCE(p) (77*(p)->c.r+150*(p)->c.g+29*(p)->c.b)
+
+static int
+splitlists(PixelList *h[3],
+ PixelList *t[3],
+ PixelList *nh[2][3],
+ PixelList *nt[2][3],
+ unsigned long nCount[2],
+ int axis,
+ unsigned long pixelCount)
+{
+ unsigned long left;
+
+ PixelList *l,*r,*c,*n;
+ int i;
+ int nRight,nLeft;
+ int splitColourVal;
+
+#ifdef TEST_SPLIT
+ {
+ PixelList *_prevTest,*_nextTest;
+ int _i,_nextCount[3],_prevCount[3];
+ for (_i=0;_i<3;_i++) {
+ for (_nextCount[_i]=0,_nextTest=h[_i];_nextTest&&_nextTest->next[_i];_nextTest=_nextTest->next[_i],_nextCount[_i]++);
+ for (_prevCount[_i]=0,_prevTest=t[_i];_prevTest&&_prevTest->prev[_i];_prevTest=_prevTest->prev[_i],_prevCount[_i]++);
+ if (_nextTest!=t[_i]) {
+ printf ("next-list of axis %d does not end at tail\n",_i);
+ exit(1);
+ }
+ if (_prevTest!=h[_i]) {
+ printf ("prev-list of axis %d does not end at head\n",_i);
+ exit(1);
+ }
+ for (;_nextTest&&_nextTest->prev[_i];_nextTest=_nextTest->prev[_i]);
+ for (;_prevTest&&_prevTest->next[_i];_prevTest=_prevTest->next[_i]);
+ if (_nextTest!=h[_i]) {
+ printf ("next-list of axis %d does not loop back to head\n",_i);
+ exit(1);
+ }
+ if (_prevTest!=t[_i]) {
+ printf ("prev-list of axis %d does not loop back to tail\n",_i);
+ exit(1);
+ }
+ }
+ for (_i=1;_i<3;_i++) {
+ if (_prevCount[_i]!=_prevCount[_i-1] ||
+ _nextCount[_i]!=_nextCount[_i-1] ||
+ _prevCount[_i]!=_nextCount[_i]) {
+ printf ("{%d %d %d} {%d %d %d}\n",
+ _prevCount[0],
+ _prevCount[1],
+ _prevCount[2],
+ _nextCount[0],
+ _nextCount[1],
+ _nextCount[2]);
+ exit(1);
+ }
+ }
+ }
+#endif
+ nCount[0]=nCount[1]=0;
+ nLeft=nRight=0;
+ for (left=0,c=h[axis];c;) {
+ left=left+c->count;
+ nCount[0]+=c->count;
+ c->flag=0;
+ nLeft++;
+ c=c->next[axis];
+ if (left*2>pixelCount) {
+ break;
+ }
+ }
+ if (c) {
+ splitColourVal=c->prev[axis]->p.a.v[axis];
+ for (;c;c=c->next[axis]) {
+ if (splitColourVal!=c->p.a.v[axis]) {
+ break;
+ }
+ c->flag=0;
+ nLeft++;
+ nCount[0]+=c->count;
+ }
+ }
+ for (;c;c=c->next[axis]) {
+ c->flag=1;
+ nRight++;
+ nCount[1]+=c->count;
+ }
+ if (!nRight) {
+ for (c=t[axis],splitColourVal=t[axis]->p.a.v[axis];c;c=c->prev[axis]) {
+ if (splitColourVal!=c->p.a.v[axis]) {
+ break;
+ }
+ c->flag=1;
+ nRight++;
+ nLeft--;
+ nCount[0]-=c->count;
+ nCount[1]+=c->count;
+ }
+ }
+#ifndef NO_OUTPUT
+ if (!nLeft) {
+ for (c=h[axis];c;c=c->next[axis]) {
+ printf ("[%d %d %d]\n",c->p.c.r,c->p.c.g,c->p.c.b);
+ }
+ printf ("warning... trivial split\n");
+ }
+#endif
+
+ for (i=0;i<3;i++) {
+ l=r=NULL;
+ nh[0][i]=nt[0][i]=NULL;
+ nh[1][i]=nt[1][i]=NULL;
+ for (c=h[i];c;c=n) {
+ n=c->next[i];
+ if (c->flag) { /* move pixel to right list*/
+ if (r) r->next[i]=c; else nh[1][i]=c;
+ c->prev[i]=r;
+ r=c;
+ } else { /* move pixel to left list */
+ if (l) l->next[i]=c; else nh[0][i]=c;
+ c->prev[i]=l;
+ l=c;
+ }
+ }
+ if (l) l->next[i]=NULL;
+ if (r) r->next[i]=NULL;
+ nt[0][i]=l;
+ nt[1][i]=r;
+ }
+ return 1;
+}
+
+static int
+split(BoxNode *node)
+{
+ unsigned char rl,rh,gl,gh,bl,bh;
+ int f[3];
+ int best,axis;
+ int i;
+ PixelList *heads[2][3];
+ PixelList *tails[2][3];
+ unsigned long newCounts[2];
+ BoxNode *left,*right;
+
+ rh=node->head[0]->p.c.r;
+ rl=node->tail[0]->p.c.r;
+ gh=node->head[1]->p.c.g;
+ gl=node->tail[1]->p.c.g;
+ bh=node->head[2]->p.c.b;
+ bl=node->tail[2]->p.c.b;
+#ifdef TEST_SPLIT
+ printf ("splitting node [%d %d %d] [%d %d %d] ",rl,gl,bl,rh,gh,bh);
+#endif
+ f[0]=(rh-rl)*77;
+ f[1]=(gh-gl)*150;
+ f[2]=(bh-bl)*29;
+
+ best=f[0];
+ axis=0;
+ for (i=1;i<3;i++) {
+ if (best<f[i]) { best=f[i]; axis=i; }
+ }
+#ifdef TEST_SPLIT
+ printf ("along axis %d\n",axis+1);
+#endif
+
+#ifdef TEST_SPLIT
+ {
+ PixelList *_prevTest,*_nextTest;
+ int _i,_nextCount[3],_prevCount[3];
+ for (_i=0;_i<3;_i++) {
+ if (node->tail[_i]->next[_i]) {
+ printf ("tail is not tail\n");
+ printf ("node->tail[%d]->next[%d]=%p\n",_i,_i,node->tail[_i]->next[_i]);
+ }
+ if (node->head[_i]->prev[_i]) {
+ printf ("head is not head\n");
+ printf ("node->head[%d]->prev[%d]=%p\n",_i,_i,node->head[_i]->prev[_i]);
+ }
+ }
+
+ for (_i=0;_i<3;_i++) {
+ for (_nextCount[_i]=0,_nextTest=node->head[_i];_nextTest&&_nextTest->next[_i];_nextTest=_nextTest->next[_i],_nextCount[_i]++);
+ for (_prevCount[_i]=0,_prevTest=node->tail[_i];_prevTest&&_prevTest->prev[_i];_prevTest=_prevTest->prev[_i],_prevCount[_i]++);
+ if (_nextTest!=node->tail[_i]) {
+ printf ("next-list of axis %d does not end at tail\n",_i);
+ }
+ if (_prevTest!=node->head[_i]) {
+ printf ("prev-list of axis %d does not end at head\n",_i);
+ }
+ for (;_nextTest&&_nextTest->prev[_i];_nextTest=_nextTest->prev[_i]);
+ for (;_prevTest&&_prevTest->next[_i];_prevTest=_prevTest->next[_i]);
+ if (_nextTest!=node->head[_i]) {
+ printf ("next-list of axis %d does not loop back to head\n",_i);
+ }
+ if (_prevTest!=node->tail[_i]) {
+ printf ("prev-list of axis %d does not loop back to tail\n",_i);
+ }
+ }
+ for (_i=1;_i<3;_i++) {
+ if (_prevCount[_i]!=_prevCount[_i-1] ||
+ _nextCount[_i]!=_nextCount[_i-1] ||
+ _prevCount[_i]!=_nextCount[_i]) {
+ printf ("{%d %d %d} {%d %d %d}\n",
+ _prevCount[0],
+ _prevCount[1],
+ _prevCount[2],
+ _nextCount[0],
+ _nextCount[1],
+ _nextCount[2]);
+ }
+ }
+ }
+#endif
+ node->axis=axis;
+ if (!splitlists(node->head,
+ node->tail,
+ heads,
+ tails,
+ newCounts,
+ axis,
+ node->pixelCount)) {
+#ifndef NO_OUTPUT
+ printf ("list split failed.\n");
+#endif
+ return 0;
+ }
+#ifdef TEST_SPLIT
+ if (!test_sorted(heads[0])) {
+ printf ("bug in split");
+ exit(1);
+ }
+ if (!test_sorted(heads[1])) {
+ printf ("bug in split");
+ exit(1);
+ }
+#endif
+ left=malloc(sizeof(BoxNode));
+ right=malloc(sizeof(BoxNode));
+ if (!left||!right) {
+ return 0;
+ }
+ for(i=0;i<3;i++) {
+ left->head[i]=heads[0][i];
+ left->tail[i]=tails[0][i];
+ right->head[i]=heads[1][i];
+ right->tail[i]=tails[1][i];
+ node->head[i]=NULL;
+ node->tail[i]=NULL;
+ }
+#ifdef TEST_SPLIT
+ if (left->head[0]) {
+ rh=left->head[0]->p.c.r;
+ rl=left->tail[0]->p.c.r;
+ gh=left->head[1]->p.c.g;
+ gl=left->tail[1]->p.c.g;
+ bh=left->head[2]->p.c.b;
+ bl=left->tail[2]->p.c.b;
+ printf (" left node [%3d %3d %3d] [%3d %3d %3d]\n",rl,gl,bl,rh,gh,bh);
+ }
+ if (right->head[0]) {
+ rh=right->head[0]->p.c.r;
+ rl=right->tail[0]->p.c.r;
+ gh=right->head[1]->p.c.g;
+ gl=right->tail[1]->p.c.g;
+ bh=right->head[2]->p.c.b;
+ bl=right->tail[2]->p.c.b;
+ printf (" right node [%3d %3d %3d] [%3d %3d %3d]\n",rl,gl,bl,rh,gh,bh);
+ }
+#endif
+ left->l=left->r=NULL;
+ right->l=right->r=NULL;
+ left->axis=right->axis=-1;
+ left->volume=right->volume=-1;
+ left->pixelCount=newCounts[0];
+ right->pixelCount=newCounts[1];
+ node->l=left;
+ node->r=right;
+ return 1;
+}
+
+static BoxNode *
+median_cut(PixelList *hl[3],
+ unsigned long imPixelCount,
+ int nPixels)
+{
+ PixelList *tl[3];
+ int i;
+ BoxNode *root;
+ Heap h;
+ BoxNode *thisNode;
+
+ h=ImagingQuantHeapNew(box_heap_cmp);
+ root=malloc(sizeof(BoxNode));
+ if (!root) { ImagingQuantHeapFree(h); return NULL; }
+ for(i=0;i<3;i++) {
+ for (tl[i]=hl[i];tl[i]&&tl[i]->next[i];tl[i]=tl[i]->next[i]);
+ root->head[i]=hl[i];
+ root->tail[i]=tl[i];
+ }
+ root->l=root->r=NULL;
+ root->axis=-1;
+ root->volume=-1;
+ root->pixelCount=imPixelCount;
+
+ ImagingQuantHeapAdd(h,(void *)root);
+ while (--nPixels) {
+ do {
+ if (!ImagingQuantHeapRemove(h,(void **)&thisNode)) {
+ goto done;
+ }
+ } while (compute_box_volume(thisNode)==1);
+ if (!split(thisNode)) {
+#ifndef NO_OUTPUT
+ printf ("Oops, split failed...\n");
+#endif
+ exit (1);
+ }
+ ImagingQuantHeapAdd(h,(void *)(thisNode->l));
+ ImagingQuantHeapAdd(h,(void *)(thisNode->r));
+ }
+ ImagingQuantHeapFree(h);
+done:
+ return root;
+}
+
+static void
+free_box_tree(BoxNode *n)
+{
+ PixelList *p,*pp;
+ if (n->l) free_box_tree(n->l);
+ if (n->r) free_box_tree(n->r);
+ for (p=n->head[0];p;p=pp) {
+ pp=p->next[0];
+ free(p);
+ }
+ free(n);
+}
+
+static int
+checkContained(BoxNode *n,Pixel *pp)
+{
+ if (n->l&&n->r) {
+ return checkContained(n->l,pp)+checkContained(n->r,pp);
+ }
+ if (n->l||n->r) {
+#ifndef NO_OUTPUT
+ printf ("box tree is dead\n");
+#endif
+ return 0;
+ }
+ if (
+ pp->c.r<=n->head[0]->p.c.r &&
+ pp->c.r>=n->tail[0]->p.c.r &&
+ pp->c.g<=n->head[1]->p.c.g &&
+ pp->c.g>=n->tail[1]->p.c.g &&
+ pp->c.b<=n->head[2]->p.c.b &&
+ pp->c.b>=n->tail[2]->p.c.b) {
+ return 1;
+ }
+ return 0;
+}
+
+static int
+annotate_hash_table(BoxNode *n,HashTable h,unsigned long *box)
+{
+ PixelList *p;
+ PixelHashData *d=(PixelHashData *)hashtable_get_user_data(h);
+ Pixel q;
+ if (n->l&&n->r) {
+ return annotate_hash_table(n->l,h,box) && annotate_hash_table(n->r,h,box);
+ }
+ if (n->l||n->r) {
+#ifndef NO_OUTPUT
+ printf ("box tree is dead\n");
+#endif
+ return 0;
+ }
+ for (p=n->head[0];p;p=p->next[0]) {
+ PIXEL_UNSCALE(&(p->p),&q,d->scale);
+ if (!hashtable_insert(h,(void *)q.v,(void *)*box)) {
+#ifndef NO_OUTPUT
+ printf ("hashtable insert failed\n");
+#endif
+ return 0;
+ }
+ }
+ if (n->head[0]) (*box)++;
+ return 1;
+}
+
+static int
+_sort_ulong_ptr_keys(const void *a, const void *b)
+{
+ unsigned long A=**(unsigned long **)a;
+ unsigned long B=**(unsigned long **)b;
+ return (A==B)?0:((A<B)?-1:+1);
+}
+
+static int
+resort_distance_tables(unsigned long *avgDist,
+ unsigned long **avgDistSortKey,
+ Pixel *p,
+ unsigned long nEntries)
+{
+ unsigned long i,j,k;
+ unsigned long **skRow;
+ unsigned long *skElt;
+
+ for (i=0;i<nEntries;i++) {
+ avgDist[i*nEntries+i]=0;
+ for (j=0;j<i;j++) {
+ avgDist[j*nEntries+i]=
+ avgDist[i*nEntries+j]=_DISTSQR(p+i,p+j);
+ }
+ }
+ for (i=0;i<nEntries;i++) {
+ skRow=avgDistSortKey+i*nEntries;
+ for (j=1;j<nEntries;j++) {
+ skElt=skRow[j];
+ for (k=j;k&&(*(skRow[k-1])>*(skRow[k]));k--) {
+ skRow[k]=skRow[k-1];
+ }
+ if (k!=j) skRow[k]=skElt;
+ }
+ }
+ return 1;
+}
+
+static int
+build_distance_tables(unsigned long *avgDist,
+ unsigned long **avgDistSortKey,
+ Pixel *p,
+ unsigned long nEntries)
+{
+ unsigned long i,j;
+
+ for (i=0;i<nEntries;i++) {
+ avgDist[i*nEntries+i]=0;
+ avgDistSortKey[i*nEntries+i]=&(avgDist[i*nEntries+i]);
+ for (j=0;j<i;j++) {
+ avgDist[j*nEntries+i]=
+ avgDist[i*nEntries+j]=_DISTSQR(p+i,p+j);
+ avgDistSortKey[j*nEntries+i]=&(avgDist[j*nEntries+i]);
+ avgDistSortKey[i*nEntries+j]=&(avgDist[i*nEntries+j]);
+ }
+ }
+ for (i=0;i<nEntries;i++) {
+ qsort(avgDistSortKey+i*nEntries,
+ nEntries,
+ sizeof(unsigned long *),
+ _sort_ulong_ptr_keys);
+ }
+ return 1;
+}
+
+static int
+map_image_pixels(Pixel *pixelData,
+ unsigned long nPixels,
+ Pixel *paletteData,
+ unsigned long nPaletteEntries,
+ unsigned long *avgDist,
+ unsigned long **avgDistSortKey,
+ unsigned long *pixelArray)
+{
+ unsigned long *aD,**aDSK;
+ unsigned long idx;
+ unsigned long i,j;
+ unsigned long bestdist,bestmatch,dist;
+ unsigned long initialdist;
+ HashTable h2;
+
+ h2=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp);
+ for (i=0;i<nPixels;i++) {
+ if (!hashtable_lookup(h2,(void *)pixelData[i].v,(void **)&bestmatch)) {
+ bestmatch=0;
+ initialdist=_DISTSQR(paletteData+bestmatch,pixelData+i);
+ bestdist=initialdist;
+ initialdist<<=2;
+ aDSK=avgDistSortKey+bestmatch*nPaletteEntries;
+ aD=avgDist+bestmatch*nPaletteEntries;
+ for (j=0;j<nPaletteEntries;j++) {
+ idx=aDSK[j]-aD;
+ if (*(aDSK[j])<=initialdist) {
+ dist=_DISTSQR(paletteData+idx,pixelData+i);
+ if (dist<bestdist) {
+ bestdist=dist;
+ bestmatch=idx;
+ }
+ } else {
+ break;
+ }
+ }
+ hashtable_insert(h2,(void *)pixelData[i].v,(void *)bestmatch);
+ }
+ pixelArray[i]=bestmatch;
+ }
+ hashtable_free(h2);
+ return 1;
+}
+
+static int
+map_image_pixels_from_quantized_pixels(
+ Pixel *pixelData,
+ unsigned long nPixels,
+ Pixel *paletteData,
+ unsigned long nPaletteEntries,
+ unsigned long *avgDist,
+ unsigned long **avgDistSortKey,
+ unsigned long *pixelArray,
+ unsigned long *avg[3],
+ unsigned long *count)
+{
+ unsigned long *aD,**aDSK;
+ unsigned long idx;
+ unsigned long i,j;
+ unsigned long bestdist,bestmatch,dist;
+ unsigned long initialdist;
+ HashTable h2;
+ int changes=0;
+
+ h2=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp);
+ for (i=0;i<nPixels;i++) {
+ if (!hashtable_lookup(h2,(void *)pixelData[i].v,(void **)&bestmatch)) {
+ bestmatch=pixelArray[i];
+ initialdist=_DISTSQR(paletteData+bestmatch,pixelData+i);
+ bestdist=initialdist;
+ initialdist<<=2;
+ aDSK=avgDistSortKey+bestmatch*nPaletteEntries;
+ aD=avgDist+bestmatch*nPaletteEntries;
+ for (j=0;j<nPaletteEntries;j++) {
+ idx=aDSK[j]-aD;
+ if (*(aDSK[j])<=initialdist) {
+ dist=_DISTSQR(paletteData+idx,pixelData+i);
+ if (dist<bestdist) {
+ bestdist=dist;
+ bestmatch=idx;
+ }
+ } else {
+ break;
+ }
+ }
+ hashtable_insert(h2,(void *)pixelData[i].v,(void *)bestmatch);
+ }
+ if (pixelArray[i]!=bestmatch) {
+ changes++;
+ avg[0][bestmatch]+=pixelData[i].c.r;
+ avg[1][bestmatch]+=pixelData[i].c.g;
+ avg[2][bestmatch]+=pixelData[i].c.b;
+ avg[0][pixelArray[i]]-=pixelData[i].c.r;
+ avg[1][pixelArray[i]]-=pixelData[i].c.g;
+ avg[2][pixelArray[i]]-=pixelData[i].c.b;
+ count[bestmatch]++;
+ count[pixelArray[i]]--;
+ pixelArray[i]=bestmatch;
+ }
+ }
+ hashtable_free(h2);
+ return changes;
+}
+
+static int
+map_image_pixels_from_median_box(
+ Pixel *pixelData,
+ unsigned long nPixels,
+ Pixel *paletteData,
+ unsigned long nPaletteEntries,
+ HashTable *medianBoxHash,
+ unsigned long *avgDist,
+ unsigned long **avgDistSortKey,
+ unsigned long *pixelArray)
+{
+ unsigned long *aD,**aDSK;
+ unsigned long idx;
+ unsigned long i,j;
+ unsigned long bestdist,bestmatch,dist;
+ unsigned long initialdist;
+ HashTable h2;
+ int pixelVal;
+
+ h2=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp);
+ for (i=0;i<nPixels;i++) {
+ if (hashtable_lookup(h2,(void *)pixelData[i].v,(void **)&pixelVal)) {
+ pixelArray[i]=pixelVal;
+ continue;
+ }
+ if (!hashtable_lookup(medianBoxHash,(void *)pixelData[i].v,(void **)&pixelVal)) {
+#ifndef NO_OUTPUT
+ printf ("pixel lookup failed\n");
+#endif
+ return 0;
+ }
+ initialdist=_DISTSQR(paletteData+pixelVal,pixelData+i);
+ bestdist=initialdist;
+ bestmatch=pixelVal;
+ initialdist<<=2;
+ aDSK=avgDistSortKey+pixelVal*nPaletteEntries;
+ aD=avgDist+pixelVal*nPaletteEntries;
+ for (j=0;j<nPaletteEntries;j++) {
+ idx=aDSK[j]-aD;
+ if (*(aDSK[j])<=initialdist) {
+ dist=_DISTSQR(paletteData+idx,pixelData+i);
+ if (dist<bestdist) {
+ bestdist=dist;
+ bestmatch=idx;
+ }
+ } else {
+ break;
+ }
+ }
+ pixelArray[i]=bestmatch;
+ hashtable_insert(h2,(void *)pixelData[i].v,(void *)bestmatch);
+ }
+ hashtable_free(h2);
+ return 1;
+}
+
+static int
+compute_palette_from_median_cut(
+ Pixel *pixelData,
+ unsigned long nPixels,
+ HashTable medianBoxHash,
+ Pixel **palette,
+ unsigned long nPaletteEntries)
+{
+ unsigned long i;
+ unsigned long paletteEntry;
+ Pixel *p;
+ unsigned long *avg[3];
+ unsigned long *count;
+
+ *palette=NULL;
+ if (!(count=malloc(sizeof(unsigned long)*nPaletteEntries))) {
+ return 0;
+ }
+ memset(count,0,sizeof(unsigned long)*nPaletteEntries);
+ for(i=0;i<3;i++) {
+ avg[i]=NULL;
+ }
+ for(i=0;i<3;i++) {
+ if (!(avg[i]=malloc(sizeof(unsigned long)*nPaletteEntries))) {
+ for(i=0;i<3;i++) {
+ if (avg[i]) free (avg[i]);
+ }
+ free(count);
+ return 0;
+ }
+ }
+ for(i=0;i<3;i++) {
+ memset(avg[i],0,sizeof(unsigned long)*nPaletteEntries);
+ }
+ for (i=0;i<nPixels;i++) {
+#ifdef TEST_SPLIT_INTEGRITY
+ if (!(i%100)) { printf ("%05d\r",i); fflush(stdout); }
+ if (checkContained(root,pixelData+i)>1) {
+ printf ("pixel in two boxes\n");
+ for(i=0;i<3;i++) free (avg[i]);
+ free(count);
+ return 0;
+ }
+#endif
+ if (!hashtable_lookup(medianBoxHash,(void *)pixelData[i].v,(void **)&paletteEntry)) {
+#ifndef NO_OUTPUT
+ printf ("pixel lookup failed\n");
+#endif
+ for(i=0;i<3;i++) free (avg[i]);
+ free(count);
+ return 0;
+ }
+ if (paletteEntry>=nPaletteEntries) {
+#ifndef NO_OUTPUT
+ printf ("panic - paletteEntry>=nPaletteEntries (%d>=%d)\n",(int)paletteEntry,(int)nPaletteEntries);
+#endif
+ for(i=0;i<3;i++) free (avg[i]);
+ free(count);
+ return 0;
+ }
+ avg[0][paletteEntry]+=pixelData[i].c.r;
+ avg[1][paletteEntry]+=pixelData[i].c.g;
+ avg[2][paletteEntry]+=pixelData[i].c.b;
+ count[paletteEntry]++;
+ }
+ p=malloc(sizeof(Pixel)*nPaletteEntries);
+ if (!p) {
+ for(i=0;i<3;i++) free (avg[i]);
+ free(count);
+ return 0;
+ }
+ for (i=0;i<nPaletteEntries;i++) {
+ p[i].c.r=(int)(.5+(double)avg[0][i]/(double)count[i]);
+ p[i].c.g=(int)(.5+(double)avg[1][i]/(double)count[i]);
+ p[i].c.b=(int)(.5+(double)avg[2][i]/(double)count[i]);
+ }
+ *palette=p;
+ for(i=0;i<3;i++) free (avg[i]);
+ free(count);
+ return 1;
+}
+
+static int
+recompute_palette_from_averages(
+ Pixel *palette,
+ unsigned long nPaletteEntries,
+ unsigned long *avg[3],
+ unsigned long *count)
+{
+ unsigned long i;
+
+ for (i=0;i<nPaletteEntries;i++) {
+ palette[i].c.r=(int)(.5+(double)avg[0][i]/(double)count[i]);
+ palette[i].c.g=(int)(.5+(double)avg[1][i]/(double)count[i]);
+ palette[i].c.b=(int)(.5+(double)avg[2][i]/(double)count[i]);
+ }
+ return 1;
+}
+
+static int
+compute_palette_from_quantized_pixels(
+ Pixel *pixelData,
+ unsigned long nPixels,
+ Pixel *palette,
+ unsigned long nPaletteEntries,
+ unsigned long *avg[3],
+ unsigned long *count,
+ unsigned long *qp)
+{
+ unsigned long i;
+
+ memset(count,0,sizeof(unsigned long)*nPaletteEntries);
+ for(i=0;i<3;i++) {
+ memset(avg[i],0,sizeof(unsigned long)*nPaletteEntries);
+ }
+ for (i=0;i<nPixels;i++) {
+ if (qp[i]>=nPaletteEntries) {
+#ifndef NO_OUTPUT
+ printf ("scream\n");
+#endif
+ return 0;
+ }
+ avg[0][qp[i]]+=pixelData[i].c.r;
+ avg[1][qp[i]]+=pixelData[i].c.g;
+ avg[2][qp[i]]+=pixelData[i].c.b;
+ count[qp[i]]++;
+ }
+ for (i=0;i<nPaletteEntries;i++) {
+ palette[i].c.r=(int)(.5+(double)avg[0][i]/(double)count[i]);
+ palette[i].c.g=(int)(.5+(double)avg[1][i]/(double)count[i]);
+ palette[i].c.b=(int)(.5+(double)avg[2][i]/(double)count[i]);
+ }
+ return 1;
+}
+
+static int
+k_means(Pixel *pixelData,
+ unsigned long nPixels,
+ Pixel *paletteData,
+ unsigned long nPaletteEntries,
+ unsigned long *qp,
+ int threshold)
+{
+ unsigned long *avg[3];
+ unsigned long *count;
+ unsigned long i;
+ unsigned long *avgDist;
+ unsigned long **avgDistSortKey;
+ int changes;
+ int built=0;
+
+ if (!(count=malloc(sizeof(unsigned long)*nPaletteEntries))) {
+ return 0;
+ }
+ for(i=0;i<3;i++) {
+ avg[i]=NULL;
+ }
+ for(i=0;i<3;i++) {
+ if (!(avg[i]=malloc(sizeof(unsigned long)*nPaletteEntries))) {
+ goto error_1;
+ }
+ }
+ avgDist=malloc(sizeof(unsigned long)*nPaletteEntries*nPaletteEntries);
+ if (!avgDist) { goto error_1; }
+
+ avgDistSortKey=malloc(sizeof(unsigned long *)*nPaletteEntries*nPaletteEntries);
+ if (!avgDistSortKey) { goto error_2; }
+
+#ifndef NO_OUTPUT
+ printf("[");fflush(stdout);
+#endif
+ while (1) {
+ if (!built) {
+ compute_palette_from_quantized_pixels(pixelData,nPixels,paletteData,nPaletteEntries,avg,count,qp);
+ build_distance_tables(avgDist,avgDistSortKey,paletteData,nPaletteEntries);
+ built=1;
+ } else {
+ recompute_palette_from_averages(paletteData,nPaletteEntries,avg,count);
+ resort_distance_tables(avgDist,avgDistSortKey,paletteData,nPaletteEntries);
+ }
+ changes=map_image_pixels_from_quantized_pixels(pixelData,
+ nPixels,
+ paletteData,
+ nPaletteEntries,
+ avgDist,
+ avgDistSortKey,
+ qp,
+ avg,
+ count);
+ if (changes<0) {
+ goto error_3;
+ }
+#ifndef NO_OUTPUT
+ printf (".(%d)",changes);fflush(stdout);
+#endif
+ if (changes<=threshold) break;
+ }
+#ifndef NO_OUTPUT
+ printf("]\n");
+#endif
+ if (avgDistSortKey) free(avgDistSortKey);
+ if (avgDist) free(avgDist);
+ for(i=0;i<3;i++) if (avg[i]) free (avg[i]);
+ if (count) free(count);
+ return 1;
+
+error_3:
+ if (avgDistSortKey) free(avgDistSortKey);
+error_2:
+ if (avgDist) free(avgDist);
+error_1:
+ for(i=0;i<3;i++) if (avg[i]) free (avg[i]);
+ if (count) free(count);
+ return 0;
+}
+
+int
+quantize(Pixel *pixelData,
+ unsigned long nPixels,
+ unsigned long nQuantPixels,
+ Pixel **palette,
+ unsigned long *paletteLength,
+ unsigned long **quantizedPixels,
+ int kmeans)
+{
+ PixelList *hl[3];
+ HashTable h;
+ BoxNode *root;
+ unsigned long i;
+ unsigned long *qp;
+ unsigned long nPaletteEntries;
+
+ unsigned long *avgDist;
+ unsigned long **avgDistSortKey;
+ Pixel *p;
+
+#ifndef NO_OUTPUT
+ unsigned long timer,timer2;
+#endif
+
+#ifndef NO_OUTPUT
+ timer2=clock();
+ printf ("create hash table..."); fflush(stdout); timer=clock();
+#endif
+ h=create_pixel_hash(pixelData,nPixels);
+#ifndef NO_OUTPUT
+ printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC);
+#endif
+ if (!h) {
+ goto error_0;
+ }
+
+#ifndef NO_OUTPUT
+ printf ("create lists from hash table..."); fflush(stdout); timer=clock();
+#endif
+ hl[0]=hl[1]=hl[2]=NULL;
+ hashtable_foreach(h,hash_to_list,hl);
+#ifndef NO_OUTPUT
+ printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC);
+#endif
+
+ if (!hl[0]) {
+ goto error_1;
+ }
+
+#ifndef NO_OUTPUT
+ printf ("mergesort lists..."); fflush(stdout); timer=clock();
+#endif
+ for(i=0;i<3;i++) {
+ hl[i]=mergesort_pixels(hl[i],i);
+ }
+#ifdef TEST_MERGESORT
+ if (!test_sorted(hl)) {
+ printf ("bug in mergesort\n");
+ goto error_1;
+ }
+#endif
+#ifndef NO_OUTPUT
+ printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC);
+#endif
+
+#ifndef NO_OUTPUT
+ printf ("median cut..."); fflush(stdout); timer=clock();
+#endif
+ root=median_cut(hl,nPixels,nQuantPixels);
+#ifndef NO_OUTPUT
+ printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC);
+#endif
+ if (!root) {
+ goto error_1;
+ }
+ nPaletteEntries=0;
+#ifndef NO_OUTPUT
+ printf ("median cut tree to hash table..."); fflush(stdout); timer=clock();
+#endif
+ annotate_hash_table(root,h,&nPaletteEntries);
+#ifndef NO_OUTPUT
+ printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC);
+#endif
+#ifndef NO_OUTPUT
+ printf ("compute palette...\n"); fflush(stdout); timer=clock();
+#endif
+ if (!compute_palette_from_median_cut(pixelData,nPixels,h,&p,nPaletteEntries)) {
+ goto error_3;
+ }
+#ifndef NO_OUTPUT
+ printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC);
+#endif
+
+ free_box_tree(root);
+ root=NULL;
+
+ qp=malloc(sizeof(unsigned long)*nPixels);
+ if (!qp) { goto error_4; }
+
+ avgDist=malloc(sizeof(unsigned long)*nPaletteEntries*nPaletteEntries);
+ if (!avgDist) { goto error_5; }
+
+ avgDistSortKey=malloc(sizeof(unsigned long *)*nPaletteEntries*nPaletteEntries);
+ if (!avgDistSortKey) { goto error_6; }
+
+ if (!build_distance_tables(avgDist,avgDistSortKey,p,nPaletteEntries)) {
+ goto error_7;
+ }
+
+ if (!map_image_pixels_from_median_box(pixelData,nPixels,p,nPaletteEntries,h,avgDist,avgDistSortKey,qp)) {
+ goto error_7;
+ }
+
+#ifdef TEST_NEAREST_NEIGHBOUR
+#include <math.h>
+ {
+ unsigned long bestmatch,bestdist,dist;
+ HashTable h2;
+ printf ("nearest neighbour search (full search)..."); fflush(stdout); timer=clock();
+ h2=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp);
+ for (i=0;i<nPixels;i++) {
+ if (hashtable_lookup(h2,(void *)pixelData[i].v,(void **)&paletteEntry)) {
+ bestmatch=paletteEntry;
+ } else {
+ bestmatch=0;
+ bestdist=
+ _SQR(pixelData[i].c.r-p[0].c.r)+
+ _SQR(pixelData[i].c.g-p[0].c.g)+
+ _SQR(pixelData[i].c.b-p[0].c.b);
+ for (j=1;j<nPaletteEntries;j++) {
+ dist=
+ _SQR(pixelData[i].c.r-p[j].c.r)+
+ _SQR(pixelData[i].c.g-p[j].c.g)+
+ _SQR(pixelData[i].c.b-p[j].c.b);
+ if (dist==bestdist && j==qp[i]) {
+ bestmatch=j;
+ }
+ if (dist<bestdist) {
+ bestdist=dist;
+ bestmatch=j;
+ }
+ }
+ hashtable_insert(h2,(void *)pixelData[i].v,(void *)bestmatch);
+ }
+ if (qp[i]!=bestmatch ) {
+ printf ("discrepancy in matching algorithms pixel %d [%d %d] %f %f\n",
+ i,qp[i],bestmatch,
+ sqrt((double)(_SQR(pixelData[i].c.r-p[qp[i]].c.r)+
+ _SQR(pixelData[i].c.g-p[qp[i]].c.g)+
+ _SQR(pixelData[i].c.b-p[qp[i]].c.b))),
+ sqrt((double)(_SQR(pixelData[i].c.r-p[bestmatch].c.r)+
+ _SQR(pixelData[i].c.g-p[bestmatch].c.g)+
+ _SQR(pixelData[i].c.b-p[bestmatch].c.b)))
+ );
+ }
+ }
+ hashtable_free(h2);
+ }
+#endif
+#ifndef NO_OUTPUT
+ printf ("k means...\n"); fflush(stdout); timer=clock();
+#endif
+ if (kmeans) k_means(pixelData,nPixels,p,nPaletteEntries,qp,kmeans-1);
+#ifndef NO_OUTPUT
+ printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC);
+#endif
+
+ *quantizedPixels=qp;
+ *palette=p;
+ *paletteLength=nPaletteEntries;
+
+#ifndef NO_OUTPUT
+ printf ("cleanup..."); fflush(stdout); timer=clock();
+#endif
+ if (avgDist) free(avgDist);
+ if (avgDistSortKey) free(avgDistSortKey);
+ destroy_pixel_hash(h);
+#ifndef NO_OUTPUT
+ printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC);
+ printf ("-----\ntotal time %f\n",(clock()-timer2)/(double)CLOCKS_PER_SEC);
+#endif
+ return 1;
+
+error_7:
+ if (avgDistSortKey) free(avgDistSortKey);
+error_6:
+ if (avgDist) free(avgDist);
+error_5:
+ if (qp) free(qp);
+error_4:
+ if (p) free(p);
+error_3:
+ if (root) free_box_tree(root);
+error_1:
+ destroy_pixel_hash(h);
+error_0:
+ *quantizedPixels=NULL;
+ *paletteLength=0;
+ *palette=NULL;
+ return 0;
+}
+
+typedef struct {
+ Pixel new;
+ Pixel furthest;
+ unsigned long furthestDistance;
+ int secondPixel;
+} DistanceData;
+
+static void
+compute_distances(const HashTable h, const void *key, void **val, void *u)
+{
+ DistanceData *data=(DistanceData *)u;
+ Pixel *pixel=(Pixel *)&key;
+ unsigned long oldDist=*(unsigned long *)val;
+ unsigned long newDist;
+ newDist=_DISTSQR(&(data->new),pixel);
+ if (data->secondPixel || newDist<oldDist) {
+ *(unsigned long *)val=newDist;
+ oldDist=newDist;
+ }
+ if (oldDist>data->furthestDistance) {
+ data->furthestDistance=oldDist;
+ data->furthest.v=pixel->v;
+ }
+}
+
+int
+quantize2(Pixel *pixelData,
+ unsigned long nPixels,
+ unsigned long nQuantPixels,
+ Pixel **palette,
+ unsigned long *paletteLength,
+ unsigned long **quantizedPixels,
+ int kmeans)
+{
+ HashTable h;
+ unsigned long i;
+ unsigned long mean[3];
+ Pixel *p;
+ DistanceData data;
+
+ unsigned long *qp;
+ unsigned long *avgDist;
+ unsigned long **avgDistSortKey;
+
+ p=malloc(sizeof(Pixel)*nQuantPixels);
+ if (!p) return 0;
+ mean[0]=mean[1]=mean[2]=0;
+ h=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp);
+ for (i=0;i<nPixels;i++) {
+ hashtable_insert(h,(void *)pixelData[i].v,(void *)0xffffffff);
+ mean[0]+=pixelData[i].c.r;
+ mean[1]+=pixelData[i].c.g;
+ mean[2]+=pixelData[i].c.b;
+ }
+ data.new.c.r=(int)(.5+(double)mean[0]/(double)nPixels);
+ data.new.c.g=(int)(.5+(double)mean[1]/(double)nPixels);
+ data.new.c.b=(int)(.5+(double)mean[2]/(double)nPixels);
+ for (i=0;i<nQuantPixels;i++) {
+ data.furthestDistance=0;
+ data.secondPixel=(i==1)?1:0;
+ hashtable_foreach_update(h,compute_distances,&data);
+ p[i].v=data.furthest.v;
+ data.new.v=data.furthest.v;
+ }
+ hashtable_free(h);
+
+ qp=malloc(sizeof(unsigned long)*nPixels);
+ if (!qp) { goto error_1; }
+
+ avgDist=malloc(sizeof(unsigned long)*nQuantPixels*nQuantPixels);
+ if (!avgDist) { goto error_2; }
+
+ avgDistSortKey=malloc(sizeof(unsigned long *)*nQuantPixels*nQuantPixels);
+ if (!avgDistSortKey) { goto error_3; }
+
+ if (!build_distance_tables(avgDist,avgDistSortKey,p,nQuantPixels)) {
+ goto error_4;
+ }
+
+ if (!map_image_pixels(pixelData,nPixels,p,nQuantPixels,avgDist,avgDistSortKey,qp)) {
+ goto error_4;
+ }
+ if (kmeans) k_means(pixelData,nPixels,p,nQuantPixels,qp,kmeans-1);
+
+ *paletteLength=nQuantPixels;
+ *palette=p;
+ *quantizedPixels=qp;
+ free(avgDistSortKey);
+ free(avgDist);
+ return 1;
+
+error_4:
+ free(avgDistSortKey);
+error_3:
+ free(avgDist);
+error_2:
+ free(qp);
+error_1:
+ free(p);
+ return 0;
+}
+
+Imaging
+ImagingQuantize(Imaging im, int colors, int mode, int kmeans)
+{
+ int i, j;
+ int x, y, v;
+ UINT8* pp;
+ Pixel* p;
+ Pixel* palette;
+ unsigned long paletteLength;
+ int result;
+ unsigned long* newData;
+ Imaging imOut;
+
+ if (!im)
+ return ImagingError_ModeError();
+ if (colors < 1 || colors > 256)
+ /* FIXME: for colors > 256, consider returning an RGB image
+ instead (see @PIL205) */
+ return (Imaging) ImagingError_ValueError("bad number of colors");
+
+ if (strcmp(im->mode, "L") != 0 && strcmp(im->mode, "P") != 0 &&
+ strcmp(im->mode, "RGB"))
+ return ImagingError_ModeError();
+
+ p = malloc(sizeof(Pixel) * im->xsize * im->ysize);
+ if (!p)
+ return ImagingError_MemoryError();
+
+ /* collect statistics */
+
+ /* FIXME: maybe we could load the hash tables directly from the
+ image data? */
+
+ if (!strcmp(im->mode, "L")) {
+ /* greyscale */
+
+ /* FIXME: converting a "L" image to "P" with 256 colors
+ should be done by a simple copy... */
+
+ for (i = y = 0; y < im->ysize; y++)
+ for (x = 0; x < im->xsize; x++, i++)
+ p[i].c.r = p[i].c.g = p[i].c.b = im->image8[y][x];
+
+ } else if (!strcmp(im->mode, "P")) {
+ /* palette */
+
+ pp = im->palette->palette;
+
+ for (i = y = 0; y < im->ysize; y++)
+ for (x = 0; x < im->xsize; x++, i++) {
+ v = im->image8[y][x];
+ p[i].c.r = pp[v*4+0];
+ p[i].c.g = pp[v*4+1];
+ p[i].c.b = pp[v*4+2];
+ }
+
+ } else if (!strcmp(im->mode, "RGB")) {
+ /* true colour */
+
+ for (i = y = 0; y < im->ysize; y++)
+ for (x = 0; x < im->xsize; x++, i++)
+ p[i].v = im->image32[y][x];
+
+ } else {
+ free(p);
+ return (Imaging) ImagingError_ValueError("internal error");
+ }
+
+ switch (mode) {
+ case 0:
+ /* median cut */
+ result = quantize(
+ p,
+ im->xsize*im->ysize,
+ colors,
+ &palette,
+ &paletteLength,
+ &newData,
+ kmeans
+ );
+ break;
+ case 1:
+ /* maximum coverage */
+ result = quantize2(
+ p,
+ im->xsize*im->ysize,
+ colors,
+ &palette,
+ &paletteLength,
+ &newData,
+ kmeans
+ );
+ break;
+ default:
+ result = 0;
+ break;
+ }
+
+ free(p);
+
+ if (result) {
+
+ imOut = ImagingNew("P", im->xsize, im->ysize);
+
+ for (i = y = 0; y < im->ysize; y++)
+ for (x=0; x < im->xsize; x++)
+ imOut->image8[y][x] = (unsigned char) newData[i++];
+
+ free(newData);
+
+ pp = imOut->palette->palette;
+
+ for (i = j = 0; i < (int) paletteLength; i++) {
+ *pp++ = palette[i].c.r;
+ *pp++ = palette[i].c.g;
+ *pp++ = palette[i].c.b;
+ *pp++ = 255;
+ }
+ for (; i < 256; i++) {
+ *pp++ = 0;
+ *pp++ = 0;
+ *pp++ = 0;
+ *pp++ = 255;
+ }
+
+ free(palette);
+
+ return imOut;
+
+ } else {
+
+ return (Imaging) ImagingError_ValueError("quantization error");
+
+ }
+}
diff --git a/Imaging/libImaging/Quant.h b/Imaging/libImaging/Quant.h
new file mode 100644
index 0000000..3626653
--- /dev/null
+++ b/Imaging/libImaging/Quant.h
@@ -0,0 +1,40 @@
+/*
+ * The Python Imaging Library
+ * $Id: Quant.h 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * image quantizer
+ *
+ * Written by Toby J Sargeant <tjs@longford.cs.monash.edu.au>.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+#ifndef __QUANT_H__
+#define __QUANT_H__
+
+typedef union {
+ struct {
+ unsigned char r,g,b,a;
+ } c;
+ struct {
+ unsigned char v[4];
+ } a;
+ unsigned long v;
+} Pixel;
+
+int quantize(Pixel *,
+ unsigned long,
+ unsigned long,
+ Pixel **,
+ unsigned long *,
+ unsigned long **,
+ int);
+
+int quantize2(Pixel *,
+ unsigned long,
+ unsigned long,
+ Pixel **,
+ unsigned long *,
+ unsigned long **,
+ int);
+#endif
diff --git a/Imaging/libImaging/QuantDefines.h b/Imaging/libImaging/QuantDefines.h
new file mode 100644
index 0000000..cba4307
--- /dev/null
+++ b/Imaging/libImaging/QuantDefines.h
@@ -0,0 +1,25 @@
+/*
+ * The Python Imaging Library
+ * $Id: QuantDefines.h 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * image quantizer
+ *
+ * Written by Toby J Sargeant <tjs@longford.cs.monash.edu.au>.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+#ifndef __DEFINES_H__
+#define __DEFINES_H__
+
+#if 0
+
+void *newMalloc(size_t,const char *,const char *,int);
+void newFree(void *,const char *,const char *,int);
+void print_malloc_stats();
+#define malloc(x) newMalloc(x,__FILE__,__FUNCTION__,__LINE__)
+#define free(x) newFree(x,__FILE__,__FUNCTION__,__LINE__)
+
+#endif
+
+#endif
diff --git a/Imaging/libImaging/QuantHash.c b/Imaging/libImaging/QuantHash.c
new file mode 100644
index 0000000..74ffca3
--- /dev/null
+++ b/Imaging/libImaging/QuantHash.c
@@ -0,0 +1,473 @@
+/*
+ * The Python Imaging Library
+ * $Id: QuantHash.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * hash tables used by the image quantizer
+ *
+ * history:
+ * 98-09-10 tjs Contributed
+ * 98-12-29 fl Added to PIL 1.0b1
+ *
+ * Written by Toby J Sargeant <tjs@longford.cs.monash.edu.au>.
+ *
+ * Copyright (c) 1998 by Toby J Sargeant
+ * Copyright (c) 1998 by Secret Labs AB
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "QuantHash.h"
+#include "QuantDefines.h"
+
+typedef struct _IntHashNode {
+ struct _IntHashNode *next;
+ void *key,*value;
+} IntHashNode;
+
+typedef struct _IntHashTable {
+ IntHashNode **table;
+ unsigned long length;
+ unsigned long count;
+ HashFunc hashFunc;
+ HashCmpFunc cmpFunc;
+ DestroyFunc keyDestroyFunc;
+ DestroyFunc valDestroyFunc;
+ void *userData;
+} IntHashTable;
+
+#define MIN_LENGTH 11
+#define RESIZE_FACTOR 3
+
+static int _hashtable_insert_node(IntHashTable *,IntHashNode *,int,int,CollisionFunc);
+static int _hashtable_test(IntHashTable *);
+
+HashTable hashtable_new(HashFunc hf,HashCmpFunc cf) {
+ IntHashTable *h;
+ h=malloc(sizeof(IntHashTable));
+ if (!h) { return NULL; }
+ h->hashFunc=hf;
+ h->cmpFunc=cf;
+ h->keyDestroyFunc=NULL;
+ h->valDestroyFunc=NULL;
+ h->length=MIN_LENGTH;
+ h->count=0;
+ h->userData=NULL;
+ h->table=malloc(sizeof(IntHashNode *)*h->length);
+ if (!h->table) { free(h); return NULL; }
+ memset (h->table,0,sizeof(IntHashNode *)*h->length);
+ return (HashTable)h;
+}
+
+static void _hashtable_destroy(HashTable H,const void *key,const void *val,void *u) {
+ IntHashTable *h=(IntHashTable *)H;
+ if (h->keyDestroyFunc&&key) {
+ h->keyDestroyFunc((HashTable)h,(void *)key);
+ }
+ if (h->valDestroyFunc&&val) {
+ h->valDestroyFunc((HashTable)h,(void *)val);
+ }
+}
+
+static unsigned long _findPrime(unsigned long start,int dir) {
+ static int unit[]={0,1,0,1,0,0,0,1,0,1,0,1,0,1,0,0};
+ unsigned long t;
+ while (start>1) {
+ if (!unit[start&0x0f]) {
+ start+=dir;
+ continue;
+ }
+ for (t=2;t<sqrt((double)start);t++) {
+ if (!start%t) break;
+ }
+ if (t>=sqrt((double)start)) {
+ break;
+ }
+ start+=dir;
+ }
+ return start;
+}
+
+static void _hashtable_rehash(IntHashTable *h,
+ CollisionFunc cf,
+ unsigned long newSize) {
+ IntHashNode **oldTable=h->table;
+ unsigned long i;
+ IntHashNode *n,*nn;
+ unsigned long oldSize;
+ oldSize=h->length;
+ h->table=malloc(sizeof(IntHashNode *)*newSize);
+ if (!h->table) {
+ h->table=oldTable;
+ return;
+ }
+ h->length=newSize;
+ h->count=0;
+ memset (h->table,0,sizeof(IntHashNode *)*h->length);
+ for (i=0;i<oldSize;i++) {
+ for (n=oldTable[i];n;n=nn) {
+ nn=n->next;
+ _hashtable_insert_node(h,n,0,0,cf);
+ }
+ }
+ free(oldTable);
+}
+
+static void _hashtable_resize(IntHashTable *h) {
+ unsigned long newSize;
+ unsigned long oldSize;
+ oldSize=h->length;
+ newSize=oldSize;
+ if (h->count*RESIZE_FACTOR<h->length) {
+ newSize=_findPrime(h->length/2-1,-1);
+ } else if (h->length*RESIZE_FACTOR<h->count) {
+ newSize=_findPrime(h->length*2+1,+1);
+ }
+ if (newSize<MIN_LENGTH) { newSize=oldSize; }
+ if (newSize!=oldSize) {
+ _hashtable_rehash(h,NULL,newSize);
+ }
+}
+
+static int _hashtable_test(IntHashTable *h) {
+ unsigned long i;
+ int j;
+ IntHashNode *n;
+ for (i=0;i<h->length;i++) {
+ for (n=h->table[i];n&&n->next;n=n->next) {
+ j=h->cmpFunc((HashTable)h,n->key,n->next->key);
+ printf ("%c",j?(j<0?'-':'+'):'=');
+ }
+ printf ("\n");
+ }
+ return 0;
+}
+
+static int _hashtable_insert_node(IntHashTable *h,IntHashNode *node,int resize,int update,CollisionFunc cf) {
+ unsigned long hash=h->hashFunc((HashTable)h,node->key)%h->length;
+ IntHashNode **n,*nv;
+ int i;
+
+ for (n=&(h->table[hash]);*n;n=&((*n)->next)) {
+ nv=*n;
+ i=h->cmpFunc((HashTable)h,nv->key,node->key);
+ if (!i) {
+ if (cf) {
+ nv->key=node->key;
+ cf((HashTable)h,&(nv->key),&(nv->value),node->key,node->value);
+ free(node);
+ return 1;
+ } else {
+ if (h->valDestroyFunc) {
+ h->valDestroyFunc((HashTable)h,nv->value);
+ }
+ if (h->keyDestroyFunc) {
+ h->keyDestroyFunc((HashTable)h,nv->key);
+ }
+ nv->key=node->key;
+ nv->value=node->value;
+ free(node);
+ return 1;
+ }
+ } else if (i>0) {
+ break;
+ }
+ }
+ if (!update) {
+ node->next=*n;
+ *n=node;
+ h->count++;
+ if (resize) _hashtable_resize(h);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int _hashtable_insert(IntHashTable *h,void *key,void *val,int resize,int update) {
+ IntHashNode **n,*nv;
+ IntHashNode *t;
+ int i;
+ unsigned long hash=h->hashFunc((HashTable)h,key)%h->length;
+
+ for (n=&(h->table[hash]);*n;n=&((*n)->next)) {
+ nv=*n;
+ i=h->cmpFunc((HashTable)h,nv->key,key);
+ if (!i) {
+ if (h->valDestroyFunc) { h->valDestroyFunc((HashTable)h,nv->value); }
+ nv->value=val;
+ return 1;
+ } else if (i>0) {
+ break;
+ }
+ }
+ if (!update) {
+ t=malloc(sizeof(IntHashNode));
+ if (!t) return 0;
+ t->next=*n;
+ *n=t;
+ t->key=key;
+ t->value=val;
+ h->count++;
+ if (resize) _hashtable_resize(h);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int _hashtable_lookup_or_insert(IntHashTable *h,void *key,void **retVal,void *newVal,int resize) {
+ IntHashNode **n,*nv;
+ IntHashNode *t;
+ int i;
+ unsigned long hash=h->hashFunc((HashTable)h,key)%h->length;
+
+ for (n=&(h->table[hash]);*n;n=&((*n)->next)) {
+ nv=*n;
+ i=h->cmpFunc((HashTable)h,nv->key,key);
+ if (!i) {
+ *retVal=nv->value;
+ return 1;
+ } else if (i>0) {
+ break;
+ }
+ }
+ t=malloc(sizeof(IntHashNode));
+ if (!t) return 0;
+ t->next=*n;
+ *n=t;
+ t->key=key;
+ t->value=newVal;
+ *retVal=newVal;
+ h->count++;
+ if (resize) _hashtable_resize(h);
+ return 1;
+}
+
+int hashtable_insert_or_update_computed(HashTable H,
+ void *key,
+ ComputeFunc newFunc,
+ ComputeFunc existsFunc) {
+ IntHashTable *h=(IntHashTable *)H;
+ IntHashNode **n,*nv;
+ IntHashNode *t;
+ int i;
+ unsigned long hash=h->hashFunc((HashTable)h,key)%h->length;
+
+ for (n=&(h->table[hash]);*n;n=&((*n)->next)) {
+ nv=*n;
+ i=h->cmpFunc((HashTable)h,nv->key,key);
+ if (!i) {
+ void *old=nv->value;
+ if (existsFunc) {
+ existsFunc(H,nv->key,&(nv->value));
+ if (nv->value!=old) {
+ if (h->valDestroyFunc) {
+ h->valDestroyFunc((HashTable)h,old);
+ }
+ }
+ } else {
+ return 0;
+ }
+ return 1;
+ } else if (i>0) {
+ break;
+ }
+ }
+ t=malloc(sizeof(IntHashNode));
+ if (!t) return 0;
+ t->key=key;
+ t->next=*n;
+ *n=t;
+ if (newFunc) {
+ newFunc(H,t->key,&(t->value));
+ } else {
+ free(t);
+ return 0;
+ }
+ h->count++;
+ _hashtable_resize(h);
+ return 1;
+}
+
+int hashtable_update(HashTable H,void *key,void *val) {
+ IntHashTable *h=(IntHashTable *)H;
+ return _hashtable_insert(h,key,val,1,0);
+}
+
+int hashtable_insert(HashTable H,void *key,void *val) {
+ IntHashTable *h=(IntHashTable *)H;
+ return _hashtable_insert(h,key,val,1,0);
+}
+
+void hashtable_foreach_update(HashTable H,IteratorUpdateFunc i,void *u) {
+ IntHashTable *h=(IntHashTable *)H;
+ IntHashNode *n;
+ unsigned long x;
+
+ if (h->table) {
+ for (x=0;x<h->length;x++) {
+ for (n=h->table[x];n;n=n->next) {
+ i((HashTable)h,n->key,(void **)&(n->value),u);
+ }
+ }
+ }
+}
+
+void hashtable_foreach(HashTable H,IteratorFunc i,void *u) {
+ IntHashTable *h=(IntHashTable *)H;
+ IntHashNode *n;
+ unsigned long x;
+
+ if (h->table) {
+ for (x=0;x<h->length;x++) {
+ for (n=h->table[x];n;n=n->next) {
+ i((HashTable)h,n->key,n->value,u);
+ }
+ }
+ }
+}
+
+void hashtable_free(HashTable H) {
+ IntHashTable *h=(IntHashTable *)H;
+ IntHashNode *n,*nn;
+ unsigned long i;
+
+ if (h->table) {
+ if (h->keyDestroyFunc || h->keyDestroyFunc) {
+ hashtable_foreach(H,_hashtable_destroy,NULL);
+ }
+ for (i=0;i<h->length;i++) {
+ for (n=h->table[i];n;n=nn) {
+ nn=n->next;
+ free(n);
+ }
+ }
+ free(h->table);
+ }
+ free(h);
+}
+
+DestroyFunc hashtable_set_value_destroy_func(HashTable H,DestroyFunc d) {
+ IntHashTable *h=(IntHashTable *)H;
+ DestroyFunc r=h->valDestroyFunc;
+ h->valDestroyFunc=d;
+ return r;
+}
+
+DestroyFunc hashtable_set_key_destroy_func(HashTable H,DestroyFunc d) {
+ IntHashTable *h=(IntHashTable *)H;
+ DestroyFunc r=h->keyDestroyFunc;
+ h->keyDestroyFunc=d;
+ return r;
+}
+
+static int _hashtable_remove(IntHashTable *h,
+ const void *key,
+ void **keyRet,
+ void **valRet,
+ int resize) {
+ unsigned long hash=h->hashFunc((HashTable)h,key)%h->length;
+ IntHashNode *n,*p;
+ int i;
+
+ for (p=NULL,n=h->table[hash];n;p=n,n=n->next) {
+ i=h->cmpFunc((HashTable)h,n->key,key);
+ if (!i) {
+ if (p) p=n->next; else h->table[hash]=n->next;
+ *keyRet=n->key;
+ *valRet=n->value;
+ free(n);
+ h->count++;
+ return 1;
+ } else if (i>0) {
+ break;
+ }
+ }
+ return 0;
+}
+
+static int _hashtable_delete(IntHashTable *h,const void *key,int resize) {
+ unsigned long hash=h->hashFunc((HashTable)h,key)%h->length;
+ IntHashNode *n,*p;
+ int i;
+
+ for (p=NULL,n=h->table[hash];n;p=n,n=n->next) {
+ i=h->cmpFunc((HashTable)h,n->key,key);
+ if (!i) {
+ if (p) p=n->next; else h->table[hash]=n->next;
+ if (h->valDestroyFunc) { h->valDestroyFunc((HashTable)h,n->value); }
+ if (h->keyDestroyFunc) { h->keyDestroyFunc((HashTable)h,n->key); }
+ free(n);
+ h->count++;
+ return 1;
+ } else if (i>0) {
+ break;
+ }
+ }
+ return 0;
+}
+
+int hashtable_remove(HashTable H,const void *key,void **keyRet,void **valRet) {
+ IntHashTable *h=(IntHashTable *)H;
+ return _hashtable_remove(h,key,keyRet,valRet,1);
+}
+
+int hashtable_delete(HashTable H,const void *key) {
+ IntHashTable *h=(IntHashTable *)H;
+ return _hashtable_delete(h,key,1);
+}
+
+void hashtable_rehash_compute(HashTable H,CollisionFunc cf) {
+ IntHashTable *h=(IntHashTable *)H;
+ _hashtable_rehash(h,cf,h->length);
+}
+
+void hashtable_rehash(HashTable H) {
+ IntHashTable *h=(IntHashTable *)H;
+ _hashtable_rehash(h,NULL,h->length);
+}
+
+int hashtable_lookup_or_insert(HashTable H,void *key,void **valp,void *val) {
+ IntHashTable *h=(IntHashTable *)H;
+ return _hashtable_lookup_or_insert(h,key,valp,val,1);
+}
+
+int hashtable_lookup(const HashTable H,const void *key,void **valp) {
+ IntHashTable *h=(IntHashTable *)H;
+ unsigned long hash=h->hashFunc((HashTable)h,key)%h->length;
+ IntHashNode *n;
+ int i;
+
+ for (n=h->table[hash];n;n=n->next) {
+ i=h->cmpFunc((HashTable)h,n->key,key);
+ if (!i) {
+ *valp=n->value;
+ return 1;
+ } else if (i>0) {
+ break;
+ }
+ }
+ return 0;
+}
+
+unsigned long hashtable_get_count(const HashTable H) {
+ IntHashTable *h=(IntHashTable *)H;
+ return h->count;
+}
+
+void *hashtable_get_user_data(const HashTable H) {
+ IntHashTable *h=(IntHashTable *)H;
+ return h->userData;
+}
+
+void *hashtable_set_user_data(HashTable H,void *data) {
+ IntHashTable *h=(IntHashTable *)H;
+ void *r=h->userData;
+ h->userData=data;
+ return r;
+}
diff --git a/Imaging/libImaging/QuantHash.h b/Imaging/libImaging/QuantHash.h
new file mode 100644
index 0000000..89d4c31
--- /dev/null
+++ b/Imaging/libImaging/QuantHash.h
@@ -0,0 +1,36 @@
+/*
+ * The Python Imaging Library
+ * $Id: QuantHash.h 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * image quantizer
+ *
+ * Written by Toby J Sargeant <tjs@longford.cs.monash.edu.au>.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+#ifndef __HASH_H__
+#define __HASH_H__
+
+#include "QuantTypes.h"
+
+HashTable hashtable_new(HashFunc,HashCmpFunc);
+void hashtable_free(HashTable);
+void hashtable_foreach(HashTable,IteratorFunc,void *);
+void hashtable_foreach_update(HashTable,IteratorUpdateFunc,void *);
+int hashtable_insert(HashTable,void *,void *);
+int hashtable_update(HashTable,void *,void *);
+int hashtable_lookup(const HashTable,const void *,void **);
+int hashtable_lookup_or_insert(HashTable,void *,void **,void *);
+int hashtable_insert_or_update_computed(HashTable,void *,ComputeFunc,ComputeFunc);
+int hashtable_delete(HashTable,const void *);
+int hashtable_remove(HashTable,const void *,void **,void **);
+void *hashtable_set_user_data(HashTable,void *);
+void *hashtable_get_user_data(const HashTable);
+DestroyFunc hashtable_set_key_destroy_func(HashTable,DestroyFunc);
+DestroyFunc hashtable_set_value_destroy_func(HashTable,DestroyFunc);
+unsigned long hashtable_get_count(const HashTable);
+void hashtable_rehash(HashTable);
+void hashtable_rehash_compute(HashTable,CollisionFunc);
+
+#endif
diff --git a/Imaging/libImaging/QuantHeap.c b/Imaging/libImaging/QuantHeap.c
new file mode 100644
index 0000000..abe7f8a
--- /dev/null
+++ b/Imaging/libImaging/QuantHeap.c
@@ -0,0 +1,150 @@
+/*
+ * The Python Imaging Library
+ * $Id: QuantHeap.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * heap data type used by the image quantizer
+ *
+ * history:
+ * 98-09-10 tjs Contributed
+ * 98-12-29 fl Added to PIL 1.0b1
+ *
+ * Written by Toby J Sargeant <tjs@longford.cs.monash.edu.au>.
+ *
+ * Copyright (c) 1998 by Toby J Sargeant
+ * Copyright (c) 1998 by Secret Labs AB
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "QuantHash.h"
+#include "QuantDefines.h"
+
+typedef struct {
+ void **heap;
+ int heapsize;
+ int heapcount;
+ HeapCmpFunc cf;
+} IntHeap;
+
+#define INITIAL_SIZE 256
+
+#define DEBUG
+
+#ifdef DEBUG
+static int _heap_test(Heap);
+#endif
+
+void ImagingQuantHeapFree(Heap H) {
+ IntHeap *h=(IntHeap *)H;
+ free(h->heap);
+ free(h);
+}
+
+static int _heap_grow(IntHeap *h,int newsize) {
+ void *newheap;
+ if (!newsize) newsize=h->heapsize<<1;
+ if (newsize<h->heapsize) return 0;
+ newheap=malloc(sizeof(void *)*newsize);
+ if (!newheap) return 0;
+ memcpy(newheap,h->heap,sizeof(void *)*h->heapsize);
+ free(h->heap);
+ h->heap=newheap;
+ h->heapsize=newsize;
+ return 1;
+}
+
+#ifdef DEBUG
+static int _heap_test(Heap H) {
+ IntHeap *h=(IntHeap *)H;
+ int k;
+ for (k=1;k*2<=h->heapcount;k++) {
+ if (h->cf(H,h->heap[k],h->heap[k*2])<0) {
+ printf ("heap is bad\n");
+ return 0;
+ }
+ if (k*2+1<=h->heapcount && h->cf(H,h->heap[k],h->heap[k*2+1])<0) {
+ printf ("heap is bad\n");
+ return 0;
+ }
+ }
+ return 1;
+}
+#endif
+
+int ImagingQuantHeapRemove(Heap H,void **r) {
+ IntHeap *h=(IntHeap *)H;
+ int k,l;
+ void *v;
+
+ if (!h->heapcount) {
+ return 0;
+ }
+ *r=h->heap[1];
+ v=h->heap[h->heapcount--];
+ for (k=1;k*2<=h->heapcount;k=l) {
+ l=k*2;
+ if (l<h->heapcount) {
+ if (h->cf(H,h->heap[l],h->heap[l+1])<0) {
+ l++;
+ }
+ }
+ if (h->cf(H,v,h->heap[l])>0) {
+ break;
+ }
+ h->heap[k]=h->heap[l];
+ }
+ h->heap[k]=v;
+#ifdef DEBUG
+ if (!_heap_test(H)) { printf ("oops - heap_remove messed up the heap\n"); exit(1); }
+#endif
+ return 1;
+}
+
+int ImagingQuantHeapAdd(Heap H,void *val) {
+ IntHeap *h=(IntHeap *)H;
+ int k;
+ if (h->heapcount==h->heapsize-1) {
+ _heap_grow(h,0);
+ }
+ k=++h->heapcount;
+ while (k!=1) {
+ if (h->cf(H,val,h->heap[k/2])<=0) {
+ break;
+ }
+ h->heap[k]=h->heap[k/2];
+ k>>=1;
+ }
+ h->heap[k]=val;
+#ifdef DEBUG
+ if (!_heap_test(H)) { printf ("oops - heap_add messed up the heap\n"); exit(1); }
+#endif
+ return 1;
+}
+
+int ImagingQuantHeapTop(Heap H,void **r) {
+ IntHeap *h=(IntHeap *)H;
+ if (!h->heapcount) {
+ return 0;
+ }
+ *r=h->heap[1];
+ return 1;
+}
+
+Heap *ImagingQuantHeapNew(HeapCmpFunc cf) {
+ IntHeap *h;
+
+ h=malloc(sizeof(IntHeap));
+ if (!h) return NULL;
+ h->heapsize=INITIAL_SIZE;
+ h->heap=malloc(sizeof(void *)*h->heapsize);
+ if (!h->heap) { free(h); return NULL; }
+ h->heapcount=0;
+ h->cf=cf;
+ return (Heap)h;
+}
+
diff --git a/Imaging/libImaging/QuantHeap.h b/Imaging/libImaging/QuantHeap.h
new file mode 100644
index 0000000..ddd0a22
--- /dev/null
+++ b/Imaging/libImaging/QuantHeap.h
@@ -0,0 +1,23 @@
+/*
+ * The Python Imaging Library
+ * $Id: QuantHeap.h 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * image quantizer
+ *
+ * Written by Toby J Sargeant <tjs@longford.cs.monash.edu.au>.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+#ifndef __HEAP_H__
+#define __HEAP_H__
+
+#include "QuantTypes.h"
+
+void ImagingQuantHeapFree(Heap);
+int ImagingQuantHeapRemove(Heap,void **);
+int ImagingQuantHeapAdd(Heap,void *);
+int ImagingQuantHeapTop(Heap,void **);
+Heap *ImagingQuantHeapNew(HeapCmpFunc);
+
+#endif
diff --git a/Imaging/libImaging/QuantTypes.h b/Imaging/libImaging/QuantTypes.h
new file mode 100644
index 0000000..0d0cd40
--- /dev/null
+++ b/Imaging/libImaging/QuantTypes.h
@@ -0,0 +1,28 @@
+/*
+ * The Python Imaging Library
+ * $Id: QuantTypes.h 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * image quantizer
+ *
+ * Written by Toby J Sargeant <tjs@longford.cs.monash.edu.au>.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+#ifndef __TYPES_H__
+#define __TYPES_H__
+
+typedef void *HashTable;
+typedef void *Heap;
+
+typedef unsigned long (*HashFunc)(const HashTable,const void *);
+typedef int (*HashCmpFunc)(const HashTable,const void *,const void *);
+typedef void (*IteratorFunc)(const HashTable,const void *,const void *,void *);
+typedef void (*IteratorUpdateFunc)(const HashTable,const void *,void **,void *);
+typedef void (*DestroyFunc)(const HashTable,void *);
+typedef void (*ComputeFunc)(const HashTable,const void *,void **);
+typedef void (*CollisionFunc)(const HashTable,void **,void **,void *,void *);
+
+typedef int (*HeapCmpFunc)(const Heap,const void *,const void *);
+
+#endif
diff --git a/Imaging/libImaging/RankFilter.c b/Imaging/libImaging/RankFilter.c
new file mode 100644
index 0000000..a0f13cd
--- /dev/null
+++ b/Imaging/libImaging/RankFilter.c
@@ -0,0 +1,105 @@
+/*
+ * The Python Imaging Library
+ * $Id: RankFilter.c 2929 2006-11-22 21:12:55Z fredrik $
+ *
+ * min, max, median filters
+ *
+ * history:
+ * 2002-06-08 fl Created
+ *
+ * Copyright (c) Secret Labs AB 2002. All rights reserved.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+#include "Imaging.h"
+
+/* Fast rank algorithm (due to Wirth), based on public domain code
+ by Nicolas Devillard, available at http://ndevilla.free.fr */
+
+#define SWAP(type,a,b) { register type t=(a);(a)=(b);(b)=t; }
+
+#define MakeRankFunction(type)\
+static type Rank##type(type a[], int n, int k)\
+{\
+ register int i, j, l, m;\
+ register type x;\
+ l = 0; m = n-1;\
+ while (l < m) {\
+ x = a[k];\
+ i = l;\
+ j = m;\
+ do {\
+ while (a[i] < x) i++;\
+ while (x < a[j]) j--;\
+ if (i <= j) {\
+ SWAP(type, a[i], a[j]);\
+ i++; j--;\
+ }\
+ } while (i <= j);\
+ if (j < k) l = i;\
+ if (k < i) m = j;\
+ }\
+ return a[k];\
+}
+
+MakeRankFunction(UINT8)
+MakeRankFunction(INT32)
+MakeRankFunction(FLOAT32)
+
+Imaging
+ImagingRankFilter(Imaging im, int size, int rank)
+{
+ Imaging imOut = NULL;
+ int x, y;
+ int i, margin, size2;
+
+ if (!im || im->bands != 1 || im->type == IMAGING_TYPE_SPECIAL)
+ return (Imaging) ImagingError_ModeError();
+
+ if (!(size & 1))
+ return (Imaging) ImagingError_ValueError("bad filter size");
+
+ size2 = size * size;
+ margin = (size-1) / 2;
+
+ if (rank < 0 || rank >= size2)
+ return (Imaging) ImagingError_ValueError("bad rank value");
+
+ imOut = ImagingNew(im->mode, im->xsize - 2*margin, im->ysize - 2*margin);
+ if (!imOut)
+ return NULL;
+
+#define RANK_BODY(type) do {\
+ type* buf = malloc(size2 * sizeof(type));\
+ if (!buf)\
+ goto nomemory;\
+ for (y = 0; y < imOut->ysize; y++)\
+ for (x = 0; x < imOut->xsize; x++) {\
+ for (i = 0; i < size; i++)\
+ memcpy(buf + i*size, &IMAGING_PIXEL_##type(im, x, y+i),\
+ size * sizeof(type));\
+ IMAGING_PIXEL_##type(imOut, x, y) = Rank##type(buf, size2, rank);\
+ }\
+} while (0)
+
+ if (im->image8)
+ RANK_BODY(UINT8);
+ else if (im->type == IMAGING_TYPE_INT32)
+ RANK_BODY(INT32);
+ else if (im->type == IMAGING_TYPE_FLOAT32)
+ RANK_BODY(FLOAT32);
+ else {
+ /* safety net (we shouldn't end up here) */
+ ImagingDelete(imOut);
+ return (Imaging) ImagingError_ModeError();
+ }
+
+ ImagingCopyInfo(imOut, im);
+
+ return imOut;
+
+nomemory:
+ ImagingDelete(imOut);
+ return (Imaging) ImagingError_MemoryError();
+}
diff --git a/Imaging/libImaging/Raw.h b/Imaging/libImaging/Raw.h
new file mode 100644
index 0000000..4d28fa5
--- /dev/null
+++ b/Imaging/libImaging/Raw.h
@@ -0,0 +1,15 @@
+/* Raw.h */
+
+typedef struct {
+
+ /* CONFIGURATION */
+
+ /* Distance between lines (0=no padding) */
+ int stride;
+
+ /* PRIVATE (initialized by decoder) */
+
+ /* Padding between lines */
+ int skip;
+
+} RAWSTATE;
diff --git a/Imaging/libImaging/RawDecode.c b/Imaging/libImaging/RawDecode.c
new file mode 100644
index 0000000..281d8c2
--- /dev/null
+++ b/Imaging/libImaging/RawDecode.c
@@ -0,0 +1,89 @@
+/*
+ * The Python Imaging Library.
+ * $Id: RawDecode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * decoder for raw (uncompressed) image data
+ *
+ * history:
+ * 96-03-07 fl rewritten
+ *
+ * Copyright (c) Fredrik Lundh 1996.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+#include "Raw.h"
+
+
+int
+ImagingRawDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ enum { LINE = 1, SKIP };
+ RAWSTATE* rawstate = state->context;
+
+ UINT8* ptr;
+
+ if (state->state == 0) {
+
+ /* Initialize context variables */
+
+ /* get size of image data and padding */
+ state->bytes = (state->xsize * state->bits + 7) / 8;
+ rawstate->skip = (rawstate->stride) ?
+ rawstate->stride - state->bytes : 0;
+
+ /* check image orientation */
+ if (state->ystep < 0) {
+ state->y = state->ysize-1;
+ state->ystep = -1;
+ } else
+ state->ystep = 1;
+
+ state->state = LINE;
+
+ }
+
+ ptr = buf;
+
+ for (;;) {
+
+ if (state->state == SKIP) {
+
+ /* Skip padding between lines */
+
+ if (bytes < rawstate->skip)
+ return ptr - buf;
+
+ ptr += rawstate->skip;
+ bytes -= rawstate->skip;
+
+ state->state = LINE;
+
+ }
+
+ if (bytes < state->bytes)
+ return ptr - buf;
+
+ /* Unpack data */
+ state->shuffle((UINT8*) im->image[state->y + state->yoff] +
+ state->xoff * im->pixelsize, ptr, state->xsize);
+
+ ptr += state->bytes;
+ bytes -= state->bytes;
+
+ state->y += state->ystep;
+
+ if (state->y < 0 || state->y >= state->ysize) {
+ /* End of file (errcode = 0) */
+ return -1;
+ }
+
+ state->state = SKIP;
+
+ }
+
+}
diff --git a/Imaging/libImaging/RawEncode.c b/Imaging/libImaging/RawEncode.c
new file mode 100644
index 0000000..945c666
--- /dev/null
+++ b/Imaging/libImaging/RawEncode.c
@@ -0,0 +1,89 @@
+/*
+ * The Python Imaging Library.
+ * $Id: RawEncode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * coder for raw data
+ *
+ * FIXME: This encoder will fail if the buffer is not large enough to
+ * hold one full line of data. There's a workaround for this problem
+ * in ImageFile.py, but it should be solved here instead.
+ *
+ * history:
+ * 96-04-30 fl created
+ * 97-01-03 fl fixed padding
+ *
+ * Copyright (c) Fredrik Lundh 1996-97.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution. */
+
+
+#include "Imaging.h"
+
+int
+ImagingRawEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ UINT8* ptr;
+
+ if (!state->state) {
+
+ /* The "count" field holds the stride, if specified. Fix
+ things up so "bytes" is the full size, and "count" the
+ packed size */
+
+ if (state->count > 0) {
+ int bytes = state->count;
+
+ /* stride must not be less than real size */
+ if (state->count < state->bytes) {
+ state->errcode = IMAGING_CODEC_CONFIG;
+ return -1;
+ }
+ state->count = state->bytes;
+ state->bytes = bytes;
+ } else
+ state->count = state->bytes;
+
+ /* The "ystep" field specifies the orientation */
+
+ if (state->ystep < 0) {
+ state->y = state->ysize-1;
+ state->ystep = -1;
+ } else
+ state->ystep = 1;
+
+ state->state = 1;
+
+ }
+
+ if (bytes < state->bytes) {
+ state->errcode = IMAGING_CODEC_CONFIG;
+ return 0;
+ }
+
+ ptr = buf;
+
+ while (bytes >= state->bytes) {
+
+ state->shuffle(ptr, (UINT8*) im->image[state->y + state->yoff] +
+ state->xoff * im->pixelsize, state->xsize);
+
+ if (state->bytes > state->count)
+ /* zero-pad the buffer, if necessary */
+ memset(ptr + state->count, 0, state->bytes - state->count);
+
+ ptr += state->bytes;
+ bytes -= state->bytes;
+
+ state->y += state->ystep;
+
+ if (state->y < 0 || state->y >= state->ysize) {
+ state->errcode = IMAGING_CODEC_END;
+ break;
+ }
+
+ }
+
+ return ptr - buf;
+
+}
diff --git a/Imaging/libImaging/Storage.c b/Imaging/libImaging/Storage.c
new file mode 100644
index 0000000..5f2ae90
--- /dev/null
+++ b/Imaging/libImaging/Storage.c
@@ -0,0 +1,399 @@
+/*
+ * The Python Imaging Library
+ * $Id: Storage.c 2542 2005-10-02 21:37:20Z Fredrik $
+ *
+ * imaging storage object
+ *
+ * This baseline implementation is designed to efficiently handle
+ * large images, provided they fit into the available memory.
+ *
+ * history:
+ * 1995-06-15 fl Created
+ * 1995-09-12 fl Updated API, compiles silently under ANSI C++
+ * 1995-11-26 fl Compiles silently under Borland 4.5 as well
+ * 1996-05-05 fl Correctly test status from Prologue
+ * 1997-05-12 fl Increased THRESHOLD (to speed up Tk interface)
+ * 1997-05-30 fl Added support for floating point images
+ * 1997-11-17 fl Added support for "RGBX" images
+ * 1998-01-11 fl Added support for integer images
+ * 1998-03-05 fl Exported Prologue/Epilogue functions
+ * 1998-07-01 fl Added basic "YCrCb" support
+ * 1998-07-03 fl Attach palette in prologue for "P" images
+ * 1998-07-09 hk Don't report MemoryError on zero-size images
+ * 1998-07-12 fl Change "YCrCb" to "YCbCr" (!)
+ * 1998-10-26 fl Added "I;16" and "I;16B" storage modes (experimental)
+ * 1998-12-29 fl Fixed allocation bug caused by previous fix
+ * 1999-02-03 fl Added "RGBa" and "BGR" modes (experimental)
+ * 2001-04-22 fl Fixed potential memory leak in ImagingCopyInfo
+ * 2003-09-26 fl Added "LA" and "PA" modes (experimental)
+ * 2005-10-02 fl Added image counter
+ *
+ * Copyright (c) 1998-2005 by Secret Labs AB
+ * Copyright (c) 1995-2005 by Fredrik Lundh
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+int ImagingNewCount = 0;
+
+/* --------------------------------------------------------------------
+ * Standard image object.
+ */
+
+Imaging
+ImagingNewPrologueSubtype(const char *mode, unsigned xsize, unsigned ysize,
+ int size)
+{
+ Imaging im;
+ ImagingSectionCookie cookie;
+
+ im = (Imaging) calloc(1, size);
+ if (!im)
+ return (Imaging) ImagingError_MemoryError();
+
+ /* Setup image descriptor */
+ im->xsize = xsize;
+ im->ysize = ysize;
+
+ im->type = IMAGING_TYPE_UINT8;
+
+ if (strcmp(mode, "1") == 0) {
+ /* 1-bit images */
+ im->bands = im->pixelsize = 1;
+ im->linesize = xsize;
+
+ } else if (strcmp(mode, "P") == 0) {
+ /* 8-bit palette mapped images */
+ im->bands = im->pixelsize = 1;
+ im->linesize = xsize;
+ im->palette = ImagingPaletteNew("RGB");
+
+ } else if (strcmp(mode, "PA") == 0) {
+ /* 8-bit palette with alpha */
+ im->bands = 2;
+ im->pixelsize = 4; /* store in image32 memory */
+ im->linesize = xsize * 4;
+ im->palette = ImagingPaletteNew("RGB");
+
+ } else if (strcmp(mode, "L") == 0) {
+ /* 8-bit greyscale (luminance) images */
+ im->bands = im->pixelsize = 1;
+ im->linesize = xsize;
+
+ } else if (strcmp(mode, "LA") == 0) {
+ /* 8-bit greyscale (luminance) with alpha */
+ im->bands = 2;
+ im->pixelsize = 4; /* store in image32 memory */
+ im->linesize = xsize * 4;
+
+ } else if (strcmp(mode, "F") == 0) {
+ /* 32-bit floating point images */
+ im->bands = 1;
+ im->pixelsize = 4;
+ im->linesize = xsize * 4;
+ im->type = IMAGING_TYPE_FLOAT32;
+
+ } else if (strcmp(mode, "I") == 0) {
+ /* 32-bit integer images */
+ im->bands = 1;
+ im->pixelsize = 4;
+ im->linesize = xsize * 4;
+ im->type = IMAGING_TYPE_INT32;
+
+ } else if (strcmp(mode, "I;16") == 0 || strcmp(mode, "I;16B") == 0) {
+ /* EXPERIMENTAL */
+ /* 16-bit raw integer images */
+ im->bands = 1;
+ im->pixelsize = 2;
+ im->linesize = xsize * 2;
+ im->type = IMAGING_TYPE_SPECIAL;
+
+ } else if (strcmp(mode, "RGB") == 0) {
+ /* 24-bit true colour images */
+ im->bands = 3;
+ im->pixelsize = 4;
+ im->linesize = xsize * 4;
+
+ } else if (strcmp(mode, "BGR;15") == 0) {
+ /* EXPERIMENTAL */
+ /* 15-bit true colour */
+ im->bands = 1;
+ im->pixelsize = 2;
+ im->linesize = (xsize*2 + 3) & -4;
+ im->type = IMAGING_TYPE_SPECIAL;
+
+ } else if (strcmp(mode, "BGR;16") == 0) {
+ /* EXPERIMENTAL */
+ /* 16-bit reversed true colour */
+ im->bands = 1;
+ im->pixelsize = 2;
+ im->linesize = (xsize*2 + 3) & -4;
+ im->type = IMAGING_TYPE_SPECIAL;
+
+ } else if (strcmp(mode, "BGR;24") == 0) {
+ /* EXPERIMENTAL */
+ /* 24-bit reversed true colour */
+ im->bands = 1;
+ im->pixelsize = 3;
+ im->linesize = (xsize*3 + 3) & -4;
+ im->type = IMAGING_TYPE_SPECIAL;
+
+ } else if (strcmp(mode, "BGR;32") == 0) {
+ /* EXPERIMENTAL */
+ /* 32-bit reversed true colour */
+ im->bands = 1;
+ im->pixelsize = 4;
+ im->linesize = (xsize*4 + 3) & -4;
+ im->type = IMAGING_TYPE_SPECIAL;
+
+ } else if (strcmp(mode, "RGBX") == 0) {
+ /* 32-bit true colour images with padding */
+ im->bands = im->pixelsize = 4;
+ im->linesize = xsize * 4;
+
+ } else if (strcmp(mode, "RGBA") == 0) {
+ /* 32-bit true colour images with alpha */
+ im->bands = im->pixelsize = 4;
+ im->linesize = xsize * 4;
+
+ } else if (strcmp(mode, "RGBa") == 0) {
+ /* EXPERIMENTAL */
+ /* 32-bit true colour images with premultiplied alpha */
+ im->bands = im->pixelsize = 4;
+ im->linesize = xsize * 4;
+
+ } else if (strcmp(mode, "CMYK") == 0) {
+ /* 32-bit colour separation */
+ im->bands = im->pixelsize = 4;
+ im->linesize = xsize * 4;
+
+ } else if (strcmp(mode, "YCbCr") == 0) {
+ /* 24-bit video format */
+ im->bands = 3;
+ im->pixelsize = 4;
+ im->linesize = xsize * 4;
+
+ } else {
+ free(im);
+ return (Imaging) ImagingError_ValueError("unrecognized mode");
+ }
+
+ /* Setup image descriptor */
+ strcpy(im->mode, mode);
+
+ ImagingSectionEnter(&cookie);
+
+ /* Pointer array (allocate at least one line, to avoid MemoryError
+ exceptions on platforms where calloc(0, x) returns NULL) */
+ im->image = (char **) calloc((ysize > 0) ? ysize : 1, sizeof(void *));
+
+ ImagingSectionLeave(&cookie);
+
+ if (!im->image) {
+ free(im);
+ return (Imaging) ImagingError_MemoryError();
+ }
+
+ ImagingNewCount++;
+
+ return im;
+}
+
+Imaging
+ImagingNewPrologue(const char *mode, unsigned xsize, unsigned ysize)
+{
+ return ImagingNewPrologueSubtype(
+ mode, xsize, ysize, sizeof(struct ImagingMemoryInstance)
+ );
+}
+
+Imaging
+ImagingNewEpilogue(Imaging im)
+{
+ /* If the raster data allocator didn't setup a destructor,
+ assume that it couldn't allocate the required amount of
+ memory. */
+ if (!im->destroy)
+ return (Imaging) ImagingError_MemoryError();
+
+ /* Initialize alias pointers to pixel data. */
+ switch (im->pixelsize) {
+ case 1: case 2: case 3:
+ im->image8 = (UINT8 **) im->image;
+ break;
+ case 4:
+ im->image32 = (INT32 **) im->image;
+ break;
+ }
+
+ return im;
+}
+
+void
+ImagingDelete(Imaging im)
+{
+ if (!im)
+ return;
+
+ if (im->palette)
+ ImagingPaletteDelete(im->palette);
+
+ if (im->destroy)
+ im->destroy(im);
+
+ if (im->image)
+ free(im->image);
+
+ free(im);
+}
+
+
+/* Array Storage Type */
+/* ------------------ */
+/* Allocate image as an array of line buffers. */
+
+static void
+ImagingDestroyArray(Imaging im)
+{
+ int y;
+
+ if (im->image)
+ for (y = 0; y < im->ysize; y++)
+ if (im->image[y])
+ free(im->image[y]);
+}
+
+Imaging
+ImagingNewArray(const char *mode, int xsize, int ysize)
+{
+ Imaging im;
+ ImagingSectionCookie cookie;
+
+ int y;
+ char* p;
+
+ im = ImagingNewPrologue(mode, xsize, ysize);
+ if (!im)
+ return NULL;
+
+ ImagingSectionEnter(&cookie);
+
+ /* Allocate image as an array of lines */
+ for (y = 0; y < im->ysize; y++) {
+ p = (char *) malloc(im->linesize);
+ if (!p) {
+ ImagingDestroyArray(im);
+ break;
+ }
+ im->image[y] = p;
+ }
+
+ ImagingSectionLeave(&cookie);
+
+ if (y == im->ysize)
+ im->destroy = ImagingDestroyArray;
+
+ return ImagingNewEpilogue(im);
+}
+
+
+/* Block Storage Type */
+/* ------------------ */
+/* Allocate image as a single block. */
+
+static void
+ImagingDestroyBlock(Imaging im)
+{
+ if (im->block)
+ free(im->block);
+}
+
+Imaging
+ImagingNewBlock(const char *mode, int xsize, int ysize)
+{
+ Imaging im;
+ int y, i;
+ int bytes;
+
+ im = ImagingNewPrologue(mode, xsize, ysize);
+ if (!im)
+ return NULL;
+
+ /* Use a single block */
+ bytes = im->ysize * im->linesize;
+ if (bytes <= 0)
+ /* some platforms return NULL for malloc(0); this fix
+ prevents MemoryError on zero-sized images on such
+ platforms */
+ bytes = 1;
+ im->block = (char *) malloc(bytes);
+
+ if (im->block) {
+
+ for (y = i = 0; y < im->ysize; y++) {
+ im->image[y] = im->block + i;
+ i += im->linesize;
+ }
+
+ im->destroy = ImagingDestroyBlock;
+
+ }
+
+ return ImagingNewEpilogue(im);
+}
+
+/* --------------------------------------------------------------------
+ * Create a new, internally allocated, image.
+ */
+#if defined(IMAGING_SMALL_MODEL)
+#define THRESHOLD 16384L
+#else
+#define THRESHOLD 1048576L
+#endif
+
+Imaging
+ImagingNew(const char* mode, int xsize, int ysize)
+{
+ /* FIXME: strlen(mode) is no longer accurate */
+ if ((long) xsize * ysize * strlen(mode) <= THRESHOLD)
+ return ImagingNewBlock(mode, xsize, ysize);
+ else
+ return ImagingNewArray(mode, xsize, ysize);
+}
+
+Imaging
+ImagingNew2(const char* mode, Imaging imOut, Imaging imIn)
+{
+ /* allocate or validate output image */
+
+ if (imOut) {
+ /* make sure images match */
+ if (strcmp(imOut->mode, mode) != 0
+ || imOut->xsize != imIn->xsize
+ || imOut->ysize != imIn->ysize) {
+ ImagingError_Mismatch();
+ return NULL;
+ }
+ } else {
+ /* create new image */
+ imOut = ImagingNew(mode, imIn->xsize, imIn->ysize);
+ if (!imOut)
+ return NULL;
+ }
+
+ return imOut;
+}
+
+void
+ImagingCopyInfo(Imaging destination, Imaging source)
+{
+ if (source->palette) {
+ if (destination->palette)
+ ImagingPaletteDelete(destination->palette);
+ destination->palette = ImagingPaletteDuplicate(source->palette);
+ }
+}
diff --git a/Imaging/libImaging/SunRleDecode.c b/Imaging/libImaging/SunRleDecode.c
new file mode 100644
index 0000000..e5171c7
--- /dev/null
+++ b/Imaging/libImaging/SunRleDecode.c
@@ -0,0 +1,112 @@
+/*
+ * THIS IS WORK IN PROGRESS
+ *
+ * The Python Imaging Library.
+ * $Id: SunRleDecode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * decoder for SUN RLE data.
+ *
+ * history:
+ * 97-01-04 fl Created
+ *
+ * Copyright (c) Fredrik Lundh 1997.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+int
+ImagingSunRleDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ int n;
+ UINT8* ptr;
+
+ ptr = buf;
+
+ for (;;) {
+
+ if (bytes < 1)
+ return ptr - buf;
+
+ if (ptr[0] == 0x80) {
+
+ if (bytes < 2)
+ break;
+
+ n = ptr[1];
+
+ if (n == 0) {
+
+ /* Literal 0x80 (2 bytes) */
+ n = 1;
+
+ state->buffer[state->x] = 0x80;
+
+ ptr += 2;
+ bytes -= 2;
+
+ } else {
+
+ /* Run (3 bytes) */
+ if (bytes < 3)
+ break;
+
+ if (state->x + n > state->bytes) {
+ /* FIXME: is this correct? */
+ state->errcode = IMAGING_CODEC_OVERRUN;
+ return -1;
+ }
+
+ memset(state->buffer + state->x, ptr[2], n);
+
+ ptr += 3;
+ bytes -= 3;
+
+ }
+
+ } else {
+
+ /* Literal (1+n bytes block) */
+ n = ptr[0];
+
+ if (bytes < 1 + n)
+ break;
+
+ if (state->x + n > state->bytes) {
+ /* FIXME: is this correct? */
+ state->errcode = IMAGING_CODEC_OVERRUN;
+ return -1;
+ }
+
+ memcpy(state->buffer + state->x, ptr + 1, n);
+
+ ptr += 1 + n;
+ bytes -= 1 + n;
+
+ }
+
+ state->x += n;
+
+ if (state->x >= state->bytes) {
+
+ /* Got a full line, unpack it */
+ state->shuffle((UINT8*) im->image[state->y + state->yoff] +
+ state->xoff * im->pixelsize, state->buffer,
+ state->xsize);
+
+ state->x = 0;
+
+ if (++state->y >= state->ysize) {
+ /* End of file (errcode = 0) */
+ return -1;
+ }
+ }
+
+ }
+
+ return ptr - buf;
+}
diff --git a/Imaging/libImaging/TgaRleDecode.c b/Imaging/libImaging/TgaRleDecode.c
new file mode 100644
index 0000000..1011f0d
--- /dev/null
+++ b/Imaging/libImaging/TgaRleDecode.c
@@ -0,0 +1,118 @@
+/*
+ * The Python Imaging Library.
+ * $Id: TgaRleDecode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * decoder for Targa RLE data.
+ *
+ * history:
+ * 97-01-04 fl created
+ * 98-09-11 fl don't one byte per pixel; take orientation into account
+ *
+ * Copyright (c) Fredrik Lundh 1997.
+ * Copyright (c) Secret Labs AB 1997-98.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+int
+ImagingTgaRleDecode(Imaging im, ImagingCodecState state,
+ UINT8* buf, int bytes)
+{
+ int n, depth;
+ UINT8* ptr;
+
+ ptr = buf;
+
+ if (state->state == 0) {
+
+ /* check image orientation */
+ if (state->ystep < 0) {
+ state->y = state->ysize-1;
+ state->ystep = -1;
+ } else
+ state->ystep = 1;
+
+ state->state = 1;
+
+ }
+
+ depth = state->count;
+
+ for (;;) {
+
+ if (bytes < 1)
+ return ptr - buf;
+
+ if (ptr[0] & 0x80) {
+
+ /* Run (1 + pixelsize bytes) */
+
+ if (bytes < 1 + depth)
+ break;
+
+ n = depth * ((ptr[0] & 0x7f) + 1);
+
+ if (state->x + n > state->bytes) {
+ state->errcode = IMAGING_CODEC_OVERRUN;
+ return -1;
+ }
+
+ if (depth == 1)
+ memset(state->buffer + state->x, ptr[1], n);
+ else {
+ int i;
+ for (i = 0; i < n; i += depth)
+ memcpy(state->buffer + state->x + i, ptr+1, depth);
+ }
+
+ ptr += 1 + depth;
+ bytes -= 1 + depth;
+
+ } else {
+
+ /* Literal (1+n+1 bytes block) */
+ n = depth * (ptr[0] + 1);
+
+ if (bytes < 1 + n)
+ break;
+
+ if (state->x + n > state->bytes) {
+ state->errcode = IMAGING_CODEC_OVERRUN;
+ return -1;
+ }
+
+ memcpy(state->buffer + state->x, ptr + 1, n);
+
+ ptr += 1 + n;
+ bytes -= 1 + n;
+
+ }
+
+ state->x += n;
+
+ if (state->x >= state->bytes) {
+
+ /* Got a full line, unpack it */
+ state->shuffle((UINT8*) im->image[state->y + state->yoff] +
+ state->xoff * im->pixelsize, state->buffer,
+ state->xsize);
+
+ state->x = 0;
+
+ state->y += state->ystep;
+
+ if (state->y < 0 || state->y >= state->ysize) {
+ /* End of file (errcode = 0) */
+ return -1;
+ }
+
+ }
+
+ }
+
+ return ptr - buf;
+}
diff --git a/Imaging/libImaging/Unpack.c b/Imaging/libImaging/Unpack.c
new file mode 100644
index 0000000..402a753
--- /dev/null
+++ b/Imaging/libImaging/Unpack.c
@@ -0,0 +1,1027 @@
+/*
+ * The Python Imaging Library.
+ * $Id: Unpack.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * code to unpack raw data from various file formats
+ *
+ * history:
+ * 1996-03-07 fl Created (from various decoders)
+ * 1996-04-19 fl Added band unpackers
+ * 1996-05-12 fl Published RGB unpackers
+ * 1996-05-27 fl Added nibble unpacker
+ * 1996-12-10 fl Added complete set of PNG unpackers
+ * 1996-12-29 fl Set alpha byte in RGB unpackers
+ * 1997-01-05 fl Added remaining TGA unpackers
+ * 1997-01-18 fl Added inverting band unpackers
+ * 1997-01-25 fl Added FlashPix unpackers
+ * 1997-05-31 fl Added floating point unpackers
+ * 1998-02-08 fl Added I unpacker
+ * 1998-07-01 fl Added YCbCr unpacker
+ * 1998-07-02 fl Added full set of integer unpackers
+ * 1998-12-29 fl Added mode field, I;16 unpackers
+ * 1998-12-30 fl Added RGBX modes
+ * 1999-02-04 fl Fixed I;16 unpackers
+ * 2003-05-13 fl Added L/RGB reversed unpackers
+ * 2003-09-26 fl Added LA/PA and RGBa->RGB unpackers
+ *
+ * Copyright (c) 1997-2003 by Secret Labs AB.
+ * Copyright (c) 1996-1997 by Fredrik Lundh.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+#include "Imaging.h"
+
+
+#define R 0
+#define G 1
+#define B 2
+#define X 3
+
+#define A 3
+
+#define C 0
+#define M 1
+#define Y 2
+#define K 3
+
+#define CLIP(x) ((x) <= 0 ? 0 : (x) < 256 ? (x) : 255)
+
+/* byte-swapping macros */
+
+#define C16N\
+ (tmp[0]=in[0], tmp[1]=in[1]);
+#define C16S\
+ (tmp[1]=in[0], tmp[0]=in[1]);
+#define C32N\
+ (tmp[0]=in[0], tmp[1]=in[1], tmp[2]=in[2], tmp[3]=in[3]);
+#define C32S\
+ (tmp[3]=in[0], tmp[2]=in[1], tmp[1]=in[2], tmp[0]=in[3]);
+#define C64N\
+ (tmp[0]=in[0], tmp[1]=in[1], tmp[2]=in[2], tmp[3]=in[3],\
+ tmp[4]=in[4], tmp[5]=in[5], tmp[6]=in[6], tmp[7]=in[7]);
+#define C64S\
+ (tmp[7]=in[0], tmp[6]=in[1], tmp[5]=in[2], tmp[4]=in[3],\
+ tmp[3]=in[4], tmp[2]=in[5], tmp[1]=in[6], tmp[0]=in[7]);
+
+#ifdef WORDS_BIGENDIAN
+#define C16B C16N
+#define C16L C16S
+#define C32B C32N
+#define C32L C32S
+#define C64B C64N
+#define C64L C64S
+#else
+#define C16B C16S
+#define C16L C16N
+#define C32B C32S
+#define C32L C32N
+#define C64B C64S
+#define C64L C64N
+#endif
+
+/* bit-swapping */
+
+static UINT8 BITFLIP[] = {
+ 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112,
+ 240, 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184,
+ 120, 248, 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52,
+ 180, 116, 244, 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220,
+ 60, 188, 124, 252, 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82,
+ 210, 50, 178, 114, 242, 10, 138, 74, 202, 42, 170, 106, 234, 26, 154,
+ 90, 218, 58, 186, 122, 250, 6, 134, 70, 198, 38, 166, 102, 230, 22,
+ 150, 86, 214, 54, 182, 118, 246, 14, 142, 78, 206, 46, 174, 110, 238,
+ 30, 158, 94, 222, 62, 190, 126, 254, 1, 129, 65, 193, 33, 161, 97,
+ 225, 17, 145, 81, 209, 49, 177, 113, 241, 9, 137, 73, 201, 41, 169,
+ 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, 5, 133, 69, 197, 37,
+ 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, 13, 141, 77, 205,
+ 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, 3, 131, 67,
+ 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, 11, 139,
+ 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, 7,
+ 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
+ 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127,
+ 255
+};
+
+/* Unpack to "1" image */
+
+static void
+unpack1(UINT8* out, const UINT8* in, int pixels)
+{
+ /* bits (msb first, white is non-zero) */
+ while (pixels > 0) {
+ UINT8 byte = *in++;
+ switch (pixels) {
+ default: *out++ = (byte & 128) ? 255 : 0; byte <<= 1;
+ case 7: *out++ = (byte & 128) ? 255 : 0; byte <<= 1;
+ case 6: *out++ = (byte & 128) ? 255 : 0; byte <<= 1;
+ case 5: *out++ = (byte & 128) ? 255 : 0; byte <<= 1;
+ case 4: *out++ = (byte & 128) ? 255 : 0; byte <<= 1;
+ case 3: *out++ = (byte & 128) ? 255 : 0; byte <<= 1;
+ case 2: *out++ = (byte & 128) ? 255 : 0; byte <<= 1;
+ case 1: *out++ = (byte & 128) ? 255 : 0;
+ }
+ pixels -= 8;
+ }
+}
+
+static void
+unpack1I(UINT8* out, const UINT8* in, int pixels)
+{
+ /* bits (msb first, white is zero) */
+ while (pixels > 0) {
+ UINT8 byte = *in++;
+ switch (pixels) {
+ default: *out++ = (byte & 128) ? 0 : 255; byte <<= 1;
+ case 7: *out++ = (byte & 128) ? 0 : 255; byte <<= 1;
+ case 6: *out++ = (byte & 128) ? 0 : 255; byte <<= 1;
+ case 5: *out++ = (byte & 128) ? 0 : 255; byte <<= 1;
+ case 4: *out++ = (byte & 128) ? 0 : 255; byte <<= 1;
+ case 3: *out++ = (byte & 128) ? 0 : 255; byte <<= 1;
+ case 2: *out++ = (byte & 128) ? 0 : 255; byte <<= 1;
+ case 1: *out++ = (byte & 128) ? 0 : 255;
+ }
+ pixels -= 8;
+ }
+}
+
+static void
+unpack1R(UINT8* out, const UINT8* in, int pixels)
+{
+ /* bits (lsb first, white is non-zero) */
+ while (pixels > 0) {
+ UINT8 byte = *in++;
+ switch (pixels) {
+ default: *out++ = (byte & 1) ? 255 : 0; byte >>= 1;
+ case 7: *out++ = (byte & 1) ? 255 : 0; byte >>= 1;
+ case 6: *out++ = (byte & 1) ? 255 : 0; byte >>= 1;
+ case 5: *out++ = (byte & 1) ? 255 : 0; byte >>= 1;
+ case 4: *out++ = (byte & 1) ? 255 : 0; byte >>= 1;
+ case 3: *out++ = (byte & 1) ? 255 : 0; byte >>= 1;
+ case 2: *out++ = (byte & 1) ? 255 : 0; byte >>= 1;
+ case 1: *out++ = (byte & 1) ? 255 : 0;
+ }
+ pixels -= 8;
+ }
+}
+
+static void
+unpack1IR(UINT8* out, const UINT8* in, int pixels)
+{
+ /* bits (lsb first, white is zero) */
+ while (pixels > 0) {
+ UINT8 byte = *in++;
+ switch (pixels) {
+ default: *out++ = (byte & 1) ? 0 : 255; byte >>= 1;
+ case 7: *out++ = (byte & 1) ? 0 : 255; byte >>= 1;
+ case 6: *out++ = (byte & 1) ? 0 : 255; byte >>= 1;
+ case 5: *out++ = (byte & 1) ? 0 : 255; byte >>= 1;
+ case 4: *out++ = (byte & 1) ? 0 : 255; byte >>= 1;
+ case 3: *out++ = (byte & 1) ? 0 : 255; byte >>= 1;
+ case 2: *out++ = (byte & 1) ? 0 : 255; byte >>= 1;
+ case 1: *out++ = (byte & 1) ? 0 : 255;
+ }
+ pixels -= 8;
+ }
+}
+
+
+/* Unpack to "L" image */
+
+static void
+unpackL2(UINT8* out, const UINT8* in, int pixels)
+{
+ /* nibbles */
+ while (pixels > 0) {
+ UINT8 byte = *in++;
+ switch (pixels) {
+ default: *out++ = ((byte >> 6) & 3) * 255 / 3; byte <<= 2;
+ case 3: *out++ = ((byte >> 6) & 3) * 255 / 3; byte <<= 2;
+ case 2: *out++ = ((byte >> 6) & 3) * 255 / 3; byte <<= 2;
+ case 1: *out++ = ((byte >> 6) & 3) * 255 / 3;
+ }
+ pixels -= 4;
+ }
+}
+
+static void
+unpackL4(UINT8* out, const UINT8* in, int pixels)
+{
+ /* nibbles */
+ while (pixels > 0) {
+ UINT8 byte = *in++;
+ switch (pixels) {
+ default: *out++ = ((byte >> 4) & 15) * 255 / 15; byte <<= 4;
+ case 1: *out++ = ((byte >> 4) & 15) * 255 / 15;
+ }
+ pixels -= 2;
+ }
+}
+
+static void
+unpackLA(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* LA, pixel interleaved */
+ for (i = 0; i < pixels; i++) {
+ out[R] = out[G] = out[B] = in[0];
+ out[A] = in[1];
+ in += 2; out += 4;
+ }
+}
+
+static void
+unpackLAL(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* LA, line interleaved */
+ for (i = 0; i < pixels; i++) {
+ out[R] = out[G] = out[B] = in[i];
+ out[A] = in[i+pixels];
+ out += 4;
+ }
+}
+
+static void
+unpackLI(UINT8* out, const UINT8* in, int pixels)
+{
+ /* negative */
+ int i;
+ for (i = 0; i < pixels; i++)
+ out[i] = ~in[i];
+}
+
+static void
+unpackLR(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* RGB, bit reversed */
+ for (i = 0; i < pixels; i++) {
+ out[i] = BITFLIP[in[i]];
+ }
+}
+
+static void
+unpackL16(UINT8* out, const UINT8* in, int pixels)
+{
+ /* int16 (upper byte, little endian) */
+ int i;
+ for (i = 0; i < pixels; i++) {
+ out[i] = in[1];
+ in += 2;
+ }
+}
+
+static void
+unpackL16B(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* int16 (upper byte, big endian) */
+ for (i = 0; i < pixels; i++) {
+ out[i] = in[0];
+ in += 2;
+ }
+}
+
+
+/* Unpack to "P" image */
+
+static void
+unpackP1(UINT8* out, const UINT8* in, int pixels)
+{
+ /* bits */
+ while (pixels > 0) {
+ UINT8 byte = *in++;
+ switch (pixels) {
+ default: *out++ = (byte >> 7) & 1; byte <<= 1;
+ case 7: *out++ = (byte >> 7) & 1; byte <<= 1;
+ case 6: *out++ = (byte >> 7) & 1; byte <<= 1;
+ case 5: *out++ = (byte >> 7) & 1; byte <<= 1;
+ case 4: *out++ = (byte >> 7) & 1; byte <<= 1;
+ case 3: *out++ = (byte >> 7) & 1; byte <<= 1;
+ case 2: *out++ = (byte >> 7) & 1; byte <<= 1;
+ case 1: *out++ = (byte >> 7) & 1;
+ }
+ pixels -= 8;
+ }
+}
+
+static void
+unpackP2(UINT8* out, const UINT8* in, int pixels)
+{
+ /* bit pairs */
+ while (pixels > 0) {
+ UINT8 byte = *in++;
+ switch (pixels) {
+ default: *out++ = (byte >> 6) & 3; byte <<= 2;
+ case 3: *out++ = (byte >> 6) & 3; byte <<= 2;
+ case 2: *out++ = (byte >> 6) & 3; byte <<= 2;
+ case 1: *out++ = (byte >> 6) & 3;
+ }
+ pixels -= 4;
+ }
+}
+
+static void
+unpackP4(UINT8* out, const UINT8* in, int pixels)
+{
+ /* nibbles */
+ while (pixels > 0) {
+ UINT8 byte = *in++;
+ switch (pixels) {
+ default: *out++ = (byte >> 4) & 15; byte <<= 4;
+ case 1: *out++ = (byte >> 4) & 15;
+ }
+ pixels -= 2;
+ }
+}
+
+static void
+unpackP2L(UINT8* out, const UINT8* in, int pixels)
+{
+ int i, j, m, s;
+ /* bit layers */
+ m = 128;
+ s = (pixels+7)/8;
+ for (i = j = 0; i < pixels; i++) {
+ out[i] = ((in[j] & m) ? 1 : 0) + ((in[j + s] & m) ? 2 : 0);
+ if ((m >>= 1) == 0) {
+ m = 128;
+ j++;
+ }
+ }
+}
+
+static void
+unpackP4L(UINT8* out, const UINT8* in, int pixels)
+{
+ int i, j, m, s;
+ /* bit layers (trust the optimizer ;-) */
+ m = 128;
+ s = (pixels+7)/8;
+ for (i = j = 0; i < pixels; i++) {
+ out[i] = ((in[j] & m) ? 1 : 0) + ((in[j + s] & m) ? 2 : 0) +
+ ((in[j + 2*s] & m) ? 4 : 0) + ((in[j + 3*s] & m) ? 8 : 0);
+ if ((m >>= 1) == 0) {
+ m = 128;
+ j++;
+ }
+ }
+}
+
+/* Unpack to "RGB" image */
+
+void
+ImagingUnpackRGB(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* RGB triplets */
+ for (i = 0; i < pixels; i++) {
+ out[R] = in[0];
+ out[G] = in[1];
+ out[B] = in[2];
+ out[A] = 255;
+ out += 4; in += 3;
+ }
+}
+
+void
+unpackRGB16B(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* 16-bit RGB triplets, big-endian order */
+ for (i = 0; i < pixels; i++) {
+ out[R] = in[0];
+ out[G] = in[2];
+ out[B] = in[4];
+ out[A] = 255;
+ out += 4; in += 6;
+ }
+}
+
+static void
+unpackRGBL(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* RGB, line interleaved */
+ for (i = 0; i < pixels; i++) {
+ out[R] = in[i];
+ out[G] = in[i+pixels];
+ out[B] = in[i+pixels+pixels];
+ out[A] = 255;
+ out += 4;
+ }
+}
+
+static void
+unpackRGBR(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* RGB, bit reversed */
+ for (i = 0; i < pixels; i++) {
+ out[R] = BITFLIP[in[0]];
+ out[G] = BITFLIP[in[1]];
+ out[B] = BITFLIP[in[2]];
+ out[A] = 255;
+ out += 4; in += 3;
+ }
+}
+
+void
+ImagingUnpackBGR(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* RGB, reversed bytes */
+ for (i = 0; i < pixels; i++) {
+ out[R] = in[2];
+ out[G] = in[1];
+ out[B] = in[0];
+ out[A] = 255;
+ out += 4; in += 3;
+ }
+}
+
+void
+ImagingUnpackBGR15(UINT8* out, const UINT8* in, int pixels)
+{
+ int i, pixel;
+ /* RGB, reversed bytes, 5 bits per pixel */
+ for (i = 0; i < pixels; i++) {
+ pixel = in[0] + (in[1] << 8);
+ out[B] = (pixel & 31) * 255 / 31;
+ out[G] = ((pixel>>5) & 31) * 255 / 31;
+ out[R] = ((pixel>>10) & 31) * 255 / 31;
+ out[A] = 255;
+ out += 4; in += 2;
+ }
+}
+
+void
+ImagingUnpackBGR16(UINT8* out, const UINT8* in, int pixels)
+{
+ int i, pixel;
+ /* RGB, reversed bytes, 5/6/5 bits per pixel */
+ for (i = 0; i < pixels; i++) {
+ pixel = in[0] + (in[1] << 8);
+ out[B] = (pixel & 31) * 255 / 31;
+ out[G] = ((pixel>>5) & 63) * 255 / 63;
+ out[R] = ((pixel>>11) & 31) * 255 / 31;
+ out[A] = 255;
+ out += 4; in += 2;
+ }
+}
+
+static void
+ImagingUnpackBGRX(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* RGB, reversed bytes with padding */
+ for (i = 0; i < pixels; i++) {
+ out[R] = in[2];
+ out[G] = in[1];
+ out[B] = in[0];
+ out[A] = 255;
+ out += 4; in += 4;
+ }
+}
+
+static void
+ImagingUnpackXRGB(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* RGB, leading pad */
+ for (i = 0; i < pixels; i++) {
+ out[R] = in[1];
+ out[G] = in[2];
+ out[B] = in[3];
+ out[A] = 255;
+ out += 4; in += 4;
+ }
+}
+
+static void
+ImagingUnpackXBGR(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* RGB, reversed bytes, leading pad */
+ for (i = 0; i < pixels; i++) {
+ out[R] = in[3];
+ out[G] = in[2];
+ out[B] = in[1];
+ out[A] = 255;
+ out += 4; in += 4;
+ }
+}
+
+/* Unpack to "RGBA" image */
+
+static void
+unpackRGBALA(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* greyscale with alpha */
+ for (i = 0; i < pixels; i++) {
+ out[R] = out[G] = out[B] = in[0];
+ out[A] = in[1];
+ out += 4; in += 2;
+ }
+}
+
+static void
+unpackRGBALA16B(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* 16-bit greyscale with alpha, big-endian */
+ for (i = 0; i < pixels; i++) {
+ out[R] = out[G] = out[B] = in[0];
+ out[A] = in[2];
+ out += 4; in += 4;
+ }
+}
+
+static void
+unpackRGBa(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* premultiplied RGBA */
+ for (i = 0; i < pixels; i++) {
+ int a = in[3];
+ if (!a)
+ out[R] = out[G] = out[B] = out[A] = 0;
+ else {
+ out[R] = CLIP(in[0] * 255 / a);
+ out[G] = CLIP(in[1] * 255 / a);
+ out[B] = CLIP(in[2] * 255 / a);
+ out[A] = a;
+ }
+ out += 4; in += 4;
+ }
+}
+
+static void
+unpackRGBAI(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* RGBA, inverted RGB bytes (FlashPix) */
+ for (i = 0; i < pixels; i++) {
+ out[R] = ~in[0];
+ out[G] = ~in[1];
+ out[B] = ~in[2];
+ out[A] = in[3];
+ out += 4; in += 4;
+ }
+}
+
+static void
+unpackRGBAL(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+
+ /* RGBA, line interleaved */
+ for (i = 0; i < pixels; i++) {
+ out[R] = in[i];
+ out[G] = in[i+pixels];
+ out[B] = in[i+pixels+pixels];
+ out[A] = in[i+pixels+pixels+pixels];
+ out += 4;
+ }
+}
+
+void
+unpackRGBA16B(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* 16-bit RGBA, big-endian order */
+ for (i = 0; i < pixels; i++) {
+ out[R] = in[0];
+ out[G] = in[2];
+ out[B] = in[4];
+ out[A] = in[6];
+ out += 4; in += 8;
+ }
+}
+
+static void
+unpackARGB(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* RGBA, leading pad */
+ for (i = 0; i < pixels; i++) {
+ out[R] = in[1];
+ out[G] = in[2];
+ out[B] = in[3];
+ out[A] = in[0];
+ out += 4; in += 4;
+ }
+}
+
+static void
+unpackABGR(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* RGBA, reversed bytes */
+ for (i = 0; i < pixels; i++) {
+ out[R] = in[3];
+ out[G] = in[2];
+ out[B] = in[1];
+ out[A] = in[0];
+ out += 4; in += 4;
+ }
+}
+
+static void
+unpackBGRA(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* RGBA, reversed bytes */
+ for (i = 0; i < pixels; i++) {
+ out[R] = in[2];
+ out[G] = in[1];
+ out[B] = in[0];
+ out[A] = in[3];
+ out += 4; in += 4;
+ }
+}
+
+
+/* Unpack to "CMYK" image */
+
+static void
+unpackCMYKI(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* CMYK, inverted bytes (Photoshop 2.5) */
+ for (i = 0; i < pixels; i++) {
+ out[C] = ~in[0];
+ out[M] = ~in[1];
+ out[Y] = ~in[2];
+ out[K] = ~in[3];
+ out += 4; in += 4;
+ }
+}
+
+static void
+copy1(UINT8* out, const UINT8* in, int pixels)
+{
+ /* L, P */
+ memcpy(out, in, pixels);
+}
+
+static void
+copy2(UINT8* out, const UINT8* in, int pixels)
+{
+ /* I;16 */
+ memcpy(out, in, pixels*2);
+}
+
+static void
+copy4(UINT8* out, const UINT8* in, int pixels)
+{
+ /* RGBA, CMYK quadruples */
+ memcpy(out, in, 4 * pixels);
+}
+
+
+/* Unpack to "I" and "F" images */
+
+#define UNPACK_RAW(NAME, GET, INTYPE, OUTTYPE)\
+static void NAME(UINT8* out_, const UINT8* in, int pixels)\
+{\
+ int i;\
+ OUTTYPE* out = (OUTTYPE*) out_;\
+ for (i = 0; i < pixels; i++, in += sizeof(INTYPE))\
+ out[i] = (OUTTYPE) ((INTYPE) GET);\
+}
+
+#define UNPACK(NAME, COPY, INTYPE, OUTTYPE)\
+static void NAME(UINT8* out_, const UINT8* in, int pixels)\
+{\
+ int i;\
+ OUTTYPE* out = (OUTTYPE*) out_;\
+ INTYPE tmp_;\
+ UINT8* tmp = (UINT8*) &tmp_;\
+ for (i = 0; i < pixels; i++, in += sizeof(INTYPE)) {\
+ COPY;\
+ out[i] = (OUTTYPE) tmp_;\
+ }\
+}
+
+UNPACK_RAW(unpackI8, in[0], UINT8, INT32)
+UNPACK_RAW(unpackI8S, in[0], INT8, INT32)
+UNPACK(unpackI16, C16L, UINT16, INT32)
+UNPACK(unpackI16S, C16L, INT16, INT32)
+UNPACK(unpackI16B, C16B, UINT16, INT32)
+UNPACK(unpackI16BS, C16B, INT16, INT32)
+UNPACK(unpackI16N, C16N, UINT16, INT32)
+UNPACK(unpackI16NS, C16N, INT16, INT32)
+UNPACK(unpackI32, C32L, UINT32, INT32)
+UNPACK(unpackI32S, C32L, INT32, INT32)
+UNPACK(unpackI32B, C32B, UINT32, INT32)
+UNPACK(unpackI32BS, C32B, INT32, INT32)
+UNPACK(unpackI32N, C32N, UINT32, INT32)
+UNPACK(unpackI32NS, C32N, INT32, INT32)
+
+UNPACK_RAW(unpackF8, in[0], UINT8, FLOAT32)
+UNPACK_RAW(unpackF8S, in[0], INT8, FLOAT32)
+UNPACK(unpackF16, C16L, UINT16, FLOAT32)
+UNPACK(unpackF16S, C16L, INT16, FLOAT32)
+UNPACK(unpackF16B, C16B, UINT16, FLOAT32)
+UNPACK(unpackF16BS, C16B, INT16, FLOAT32)
+UNPACK(unpackF16N, C16N, UINT16, FLOAT32)
+UNPACK(unpackF16NS, C16N, INT16, FLOAT32)
+UNPACK(unpackF32, C32L, UINT32, FLOAT32)
+UNPACK(unpackF32S, C32L, INT32, FLOAT32)
+UNPACK(unpackF32B, C32B, UINT32, FLOAT32)
+UNPACK(unpackF32BS, C32B, INT32, FLOAT32)
+UNPACK(unpackF32N, C32N, UINT32, FLOAT32)
+UNPACK(unpackF32NS, C32N, INT32, FLOAT32)
+UNPACK(unpackF32F, C32L, FLOAT32, FLOAT32)
+UNPACK(unpackF32BF, C32B, FLOAT32, FLOAT32)
+UNPACK(unpackF32NF, C32N, FLOAT32, FLOAT32)
+#ifdef FLOAT64
+UNPACK(unpackF64F, C64L, FLOAT64, FLOAT32)
+UNPACK(unpackF64BF, C64B, FLOAT64, FLOAT32)
+UNPACK(unpackF64NF, C64N, FLOAT64, FLOAT32)
+#endif
+
+
+/* Misc. unpackers */
+
+static void
+band0(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* band 0 only */
+ for (i = 0; i < pixels; i++) {
+ out[0] = in[i];
+ out += 4;
+ }
+}
+
+static void
+band1(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* band 1 only */
+ for (i = 0; i < pixels; i++) {
+ out[1] = in[i];
+ out += 4;
+ }
+}
+
+static void
+band2(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* band 2 only */
+ for (i = 0; i < pixels; i++) {
+ out[2] = in[i];
+ out += 4;
+ }
+}
+
+static void
+band3(UINT8* out, const UINT8* in, int pixels)
+{
+ /* band 3 only */
+ int i;
+ for (i = 0; i < pixels; i++) {
+ out[3] = in[i];
+ out += 4;
+ }
+}
+
+static void
+band0I(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* band 0 only */
+ for (i = 0; i < pixels; i++) {
+ out[0] = ~in[i];
+ out += 4;
+ }
+}
+
+static void
+band1I(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* band 1 only */
+ for (i = 0; i < pixels; i++) {
+ out[1] = ~in[i];
+ out += 4;
+ }
+}
+
+static void
+band2I(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* band 2 only */
+ for (i = 0; i < pixels; i++) {
+ out[2] = ~in[i];
+ out += 4;
+ }
+}
+
+static void
+band3I(UINT8* out, const UINT8* in, int pixels)
+{
+ /* band 3 only */
+ int i;
+ for (i = 0; i < pixels; i++) {
+ out[3] = ~in[i];
+ out += 4;
+ }
+}
+
+static struct {
+ const char* mode;
+ const char* rawmode;
+ int bits;
+ ImagingShuffler unpack;
+} unpackers[] = {
+
+ /* raw mode syntax is "<mode>;<bits><flags>" where "bits" defaults
+ depending on mode (1 for "1", 8 for "P" and "L", etc), and
+ "flags" should be given in alphabetical order. if both bits
+ and flags have their default values, the ; should be left out */
+
+ /* flags: "I" inverted data; "R" reversed bit order; "B" big
+ endian byte order (default is little endian); "L" line
+ interleave, "S" signed, "F" floating point */
+
+ /* bilevel */
+ {"1", "1", 1, unpack1},
+ {"1", "1;I", 1, unpack1I},
+ {"1", "1;R", 1, unpack1R},
+ {"1", "1;IR", 1, unpack1IR},
+
+ /* greyscale */
+ {"L", "L;2", 2, unpackL2},
+ {"L", "L;4", 4, unpackL4},
+ {"L", "L", 8, copy1},
+ {"L", "L;I", 8, unpackLI},
+ {"L", "L;R", 8, unpackLR},
+ {"L", "L;16", 16, unpackL16},
+ {"L", "L;16B", 16, unpackL16B},
+
+ /* greyscale w. alpha */
+ {"LA", "LA", 16, unpackLA},
+ {"LA", "LA;L", 16, unpackLAL},
+
+ /* palette */
+ {"P", "P;1", 1, unpackP1},
+ {"P", "P;2", 2, unpackP2},
+ {"P", "P;2L", 2, unpackP2L},
+ {"P", "P;4", 4, unpackP4},
+ {"P", "P;4L", 4, unpackP4L},
+ {"P", "P", 8, copy1},
+ {"P", "P;R", 8, unpackLR},
+
+ /* palette w. alpha */
+ {"PA", "PA", 16, unpackLA},
+ {"PA", "PA;L", 16, unpackLAL},
+
+ /* true colour */
+ {"RGB", "RGB", 24, ImagingUnpackRGB},
+ {"RGB", "RGB;L", 24, unpackRGBL},
+ {"RGB", "RGB;R", 24, unpackRGBR},
+ {"RGB", "RGB;16B", 48, unpackRGB16B},
+ {"RGB", "BGR", 24, ImagingUnpackBGR},
+ {"RGB", "BGR;15", 16, ImagingUnpackBGR15},
+ {"RGB", "BGR;16", 16, ImagingUnpackBGR16},
+ {"RGB", "BGR;5", 16, ImagingUnpackBGR15}, /* compat */
+ {"RGB", "RGBX", 32, copy4},
+ {"RGB", "RGBX;L", 32, unpackRGBAL},
+ {"RGB", "BGRX", 32, ImagingUnpackBGRX},
+ {"RGB", "XRGB", 24, ImagingUnpackXRGB},
+ {"RGB", "XBGR", 32, ImagingUnpackXBGR},
+ {"RGB", "YCC;P", 24, ImagingUnpackYCC},
+ {"RGB", "R", 8, band0},
+ {"RGB", "G", 8, band1},
+ {"RGB", "B", 8, band2},
+
+ /* true colour w. alpha */
+ {"RGBA", "LA", 16, unpackRGBALA},
+ {"RGBA", "LA;16B", 32, unpackRGBALA16B},
+ {"RGBA", "RGBA", 32, copy4},
+ {"RGBA", "RGBa", 32, unpackRGBa},
+ {"RGBA", "RGBA;I", 32, unpackRGBAI},
+ {"RGBA", "RGBA;L", 32, unpackRGBAL},
+ {"RGBA", "RGBA;16B", 64, unpackRGBA16B},
+ {"RGBA", "BGRA", 32, unpackBGRA},
+ {"RGBA", "ARGB", 32, unpackARGB},
+ {"RGBA", "ABGR", 32, unpackABGR},
+ {"RGBA", "YCCA;P", 32, ImagingUnpackYCCA},
+ {"RGBA", "R", 8, band0},
+ {"RGBA", "G", 8, band1},
+ {"RGBA", "B", 8, band2},
+ {"RGBA", "A", 8, band3},
+
+ /* true colour w. padding */
+ {"RGBX", "RGB", 24, ImagingUnpackRGB},
+ {"RGBX", "RGB;L", 24, unpackRGBL},
+ {"RGBX", "RGB;16B", 48, unpackRGB16B},
+ {"RGBX", "BGR", 24, ImagingUnpackBGR},
+ {"RGBX", "BGR;15", 16, ImagingUnpackBGR15},
+ {"RGB", "BGR;16", 16, ImagingUnpackBGR16},
+ {"RGBX", "BGR;5", 16, ImagingUnpackBGR15}, /* compat */
+ {"RGBX", "RGBX", 32, copy4},
+ {"RGBX", "RGBX;L", 32, unpackRGBAL},
+ {"RGBX", "BGRX", 32, ImagingUnpackBGRX},
+ {"RGBX", "XRGB", 24, ImagingUnpackXRGB},
+ {"RGBX", "XBGR", 32, ImagingUnpackXBGR},
+ {"RGBX", "YCC;P", 24, ImagingUnpackYCC},
+ {"RGBX", "R", 8, band0},
+ {"RGBX", "G", 8, band1},
+ {"RGBX", "B", 8, band2},
+ {"RGBX", "X", 8, band3},
+
+ /* colour separation */
+ {"CMYK", "CMYK", 32, copy4},
+ {"CMYK", "CMYK;I", 32, unpackCMYKI},
+ {"CMYK", "CMYK;L", 32, unpackRGBAL},
+ {"CMYK", "C", 8, band0},
+ {"CMYK", "M", 8, band1},
+ {"CMYK", "Y", 8, band2},
+ {"CMYK", "K", 8, band3},
+ {"CMYK", "C;I", 8, band0I},
+ {"CMYK", "M;I", 8, band1I},
+ {"CMYK", "Y;I", 8, band2I},
+ {"CMYK", "K;I", 8, band3I},
+
+ /* video (YCbCr) */
+ {"YCbCr", "YCbCr", 24, ImagingUnpackRGB},
+ {"YCbCr", "YCbCr;L", 24, unpackRGBL},
+ {"YCbCr", "YCbCrX", 32, copy4},
+ {"YCbCr", "YCbCrK", 32, copy4},
+
+ /* integer variations */
+ {"I", "I", 32, copy4},
+ {"I", "I;8", 8, unpackI8},
+ {"I", "I;8S", 8, unpackI8S},
+ {"I", "I;16", 16, unpackI16},
+ {"I", "I;16S", 16, unpackI16S},
+ {"I", "I;16B", 16, unpackI16B},
+ {"I", "I;16BS", 16, unpackI16BS},
+ {"I", "I;16N", 16, unpackI16N},
+ {"I", "I;16NS", 16, unpackI16NS},
+ {"I", "I;32", 32, unpackI32},
+ {"I", "I;32S", 32, unpackI32S},
+ {"I", "I;32B", 32, unpackI32B},
+ {"I", "I;32BS", 32, unpackI32BS},
+ {"I", "I;32N", 32, unpackI32N},
+ {"I", "I;32NS", 32, unpackI32NS},
+
+ /* floating point variations */
+ {"F", "F", 32, copy4},
+ {"F", "F;8", 8, unpackF8},
+ {"F", "F;8S", 8, unpackF8S},
+ {"F", "F;16", 16, unpackF16},
+ {"F", "F;16S", 16, unpackF16S},
+ {"F", "F;16B", 16, unpackF16B},
+ {"F", "F;16BS", 16, unpackF16BS},
+ {"F", "F;16N", 16, unpackF16N},
+ {"F", "F;16NS", 16, unpackF16NS},
+ {"F", "F;32", 32, unpackF32},
+ {"F", "F;32S", 32, unpackF32S},
+ {"F", "F;32B", 32, unpackF32B},
+ {"F", "F;32BS", 32, unpackF32BS},
+ {"F", "F;32N", 32, unpackF32N},
+ {"F", "F;32NS", 32, unpackF32NS},
+ {"F", "F;32F", 32, unpackF32F},
+ {"F", "F;32BF", 32, unpackF32BF},
+ {"F", "F;32NF", 32, unpackF32NF},
+#ifdef FLOAT64
+ {"F", "F;64F", 64, unpackF64F},
+ {"F", "F;64BF", 64, unpackF64BF},
+ {"F", "F;64NF", 64, unpackF64NF},
+#endif
+
+ /* storage modes */
+ {"I;16", "I;16", 16, copy2},
+ {"I;16B", "I;16B", 16, copy2},
+
+ {NULL} /* sentinel */
+};
+
+
+ImagingShuffler
+ImagingFindUnpacker(const char* mode, const char* rawmode, int* bits_out)
+{
+ int i;
+
+ /* find a suitable pixel unpacker */
+ for (i = 0; unpackers[i].rawmode; i++)
+ if (strcmp(unpackers[i].mode, mode) == 0 &&
+ strcmp(unpackers[i].rawmode, rawmode) == 0) {
+ if (bits_out)
+ *bits_out = unpackers[i].bits;
+ return unpackers[i].unpack;
+ }
+
+ /* FIXME: configure a general unpacker based on the type codes... */
+
+ return NULL;
+}
diff --git a/Imaging/libImaging/UnpackYCC.c b/Imaging/libImaging/UnpackYCC.c
new file mode 100644
index 0000000..421e901
--- /dev/null
+++ b/Imaging/libImaging/UnpackYCC.c
@@ -0,0 +1,162 @@
+/*
+ * The Python Imaging Library.
+ * $Id: UnpackYCC.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * code to convert and unpack PhotoYCC data
+ *
+ * history:
+ * 97-01-25 fl Moved from PcdDecode.c
+ *
+ * Copyright (c) Fredrik Lundh 1996-97.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+/* Tables generated by pcdtables.py, based on transforms taken from
+ the "Colour Space Conversions FAQ" by Roberts/Ford. */
+
+static INT16 L[] = { 0, 1, 3, 4, 5, 7, 8, 10, 11, 12, 14, 15, 16, 18,
+19, 20, 22, 23, 24, 26, 27, 29, 30, 31, 33, 34, 35, 37, 38, 39, 41,
+42, 43, 45, 46, 48, 49, 50, 52, 53, 54, 56, 57, 58, 60, 61, 62, 64,
+65, 67, 68, 69, 71, 72, 73, 75, 76, 77, 79, 80, 82, 83, 84, 86, 87,
+88, 90, 91, 92, 94, 95, 96, 98, 99, 101, 102, 103, 105, 106, 107, 109,
+110, 111, 113, 114, 115, 117, 118, 120, 121, 122, 124, 125, 126, 128,
+129, 130, 132, 133, 134, 136, 137, 139, 140, 141, 143, 144, 145, 147,
+148, 149, 151, 152, 153, 155, 156, 158, 159, 160, 162, 163, 164, 166,
+167, 168, 170, 171, 173, 174, 175, 177, 178, 179, 181, 182, 183, 185,
+186, 187, 189, 190, 192, 193, 194, 196, 197, 198, 200, 201, 202, 204,
+205, 206, 208, 209, 211, 212, 213, 215, 216, 217, 219, 220, 221, 223,
+224, 225, 227, 228, 230, 231, 232, 234, 235, 236, 238, 239, 240, 242,
+243, 245, 246, 247, 249, 250, 251, 253, 254, 255, 257, 258, 259, 261,
+262, 264, 265, 266, 268, 269, 270, 272, 273, 274, 276, 277, 278, 280,
+281, 283, 284, 285, 287, 288, 289, 291, 292, 293, 295, 296, 297, 299,
+300, 302, 303, 304, 306, 307, 308, 310, 311, 312, 314, 315, 317, 318,
+319, 321, 322, 323, 325, 326, 327, 329, 330, 331, 333, 334, 336, 337,
+338, 340, 341, 342, 344, 345, 346 };
+
+static INT16 CB[] = { -345, -343, -341, -338, -336, -334, -332, -329,
+-327, -325, -323, -321, -318, -316, -314, -312, -310, -307, -305,
+-303, -301, -298, -296, -294, -292, -290, -287, -285, -283, -281,
+-278, -276, -274, -272, -270, -267, -265, -263, -261, -258, -256,
+-254, -252, -250, -247, -245, -243, -241, -239, -236, -234, -232,
+-230, -227, -225, -223, -221, -219, -216, -214, -212, -210, -207,
+-205, -203, -201, -199, -196, -194, -192, -190, -188, -185, -183,
+-181, -179, -176, -174, -172, -170, -168, -165, -163, -161, -159,
+-156, -154, -152, -150, -148, -145, -143, -141, -139, -137, -134,
+-132, -130, -128, -125, -123, -121, -119, -117, -114, -112, -110,
+-108, -105, -103, -101, -99, -97, -94, -92, -90, -88, -85, -83, -81,
+-79, -77, -74, -72, -70, -68, -66, -63, -61, -59, -57, -54, -52, -50,
+-48, -46, -43, -41, -39, -37, -34, -32, -30, -28, -26, -23, -21, -19,
+-17, -15, -12, -10, -8, -6, -3, -1, 0, 2, 4, 7, 9, 11, 13, 16, 18, 20,
+22, 24, 27, 29, 31, 33, 35, 38, 40, 42, 44, 47, 49, 51, 53, 55, 58,
+60, 62, 64, 67, 69, 71, 73, 75, 78, 80, 82, 84, 86, 89, 91, 93, 95,
+98, 100, 102, 104, 106, 109, 111, 113, 115, 118, 120, 122, 124, 126,
+129, 131, 133, 135, 138, 140, 142, 144, 146, 149, 151, 153, 155, 157,
+160, 162, 164, 166, 169, 171, 173, 175, 177, 180, 182, 184, 186, 189,
+191, 193, 195, 197, 200, 202, 204, 206, 208, 211, 213, 215, 217, 220 };
+
+static INT16 GB[] = { 67, 67, 66, 66, 65, 65, 65, 64, 64, 63, 63, 62,
+62, 62, 61, 61, 60, 60, 59, 59, 59, 58, 58, 57, 57, 56, 56, 56, 55,
+55, 54, 54, 53, 53, 52, 52, 52, 51, 51, 50, 50, 49, 49, 49, 48, 48,
+47, 47, 46, 46, 46, 45, 45, 44, 44, 43, 43, 43, 42, 42, 41, 41, 40,
+40, 40, 39, 39, 38, 38, 37, 37, 37, 36, 36, 35, 35, 34, 34, 34, 33,
+33, 32, 32, 31, 31, 31, 30, 30, 29, 29, 28, 28, 28, 27, 27, 26, 26,
+25, 25, 25, 24, 24, 23, 23, 22, 22, 22, 21, 21, 20, 20, 19, 19, 19,
+18, 18, 17, 17, 16, 16, 15, 15, 15, 14, 14, 13, 13, 12, 12, 12, 11,
+11, 10, 10, 9, 9, 9, 8, 8, 7, 7, 6, 6, 6, 5, 5, 4, 4, 3, 3, 3, 2, 2,
+1, 1, 0, 0, 0, 0, 0, -1, -1, -2, -2, -2, -3, -3, -4, -4, -5, -5, -5,
+-6, -6, -7, -7, -8, -8, -8, -9, -9, -10, -10, -11, -11, -11, -12, -12,
+-13, -13, -14, -14, -14, -15, -15, -16, -16, -17, -17, -18, -18, -18,
+-19, -19, -20, -20, -21, -21, -21, -22, -22, -23, -23, -24, -24, -24,
+-25, -25, -26, -26, -27, -27, -27, -28, -28, -29, -29, -30, -30, -30,
+-31, -31, -32, -32, -33, -33, -33, -34, -34, -35, -35, -36, -36, -36,
+-37, -37, -38, -38, -39, -39, -39, -40, -40, -41, -41, -42 };
+
+static INT16 CR[] = { -249, -247, -245, -243, -241, -239, -238, -236,
+-234, -232, -230, -229, -227, -225, -223, -221, -219, -218, -216,
+-214, -212, -210, -208, -207, -205, -203, -201, -199, -198, -196,
+-194, -192, -190, -188, -187, -185, -183, -181, -179, -178, -176,
+-174, -172, -170, -168, -167, -165, -163, -161, -159, -157, -156,
+-154, -152, -150, -148, -147, -145, -143, -141, -139, -137, -136,
+-134, -132, -130, -128, -127, -125, -123, -121, -119, -117, -116,
+-114, -112, -110, -108, -106, -105, -103, -101, -99, -97, -96, -94,
+-92, -90, -88, -86, -85, -83, -81, -79, -77, -76, -74, -72, -70, -68,
+-66, -65, -63, -61, -59, -57, -55, -54, -52, -50, -48, -46, -45, -43,
+-41, -39, -37, -35, -34, -32, -30, -28, -26, -25, -23, -21, -19, -17,
+-15, -14, -12, -10, -8, -6, -4, -3, -1, 0, 2, 4, 5, 7, 9, 11, 13, 15,
+16, 18, 20, 22, 24, 26, 27, 29, 31, 33, 35, 36, 38, 40, 42, 44, 46,
+47, 49, 51, 53, 55, 56, 58, 60, 62, 64, 66, 67, 69, 71, 73, 75, 77,
+78, 80, 82, 84, 86, 87, 89, 91, 93, 95, 97, 98, 100, 102, 104, 106,
+107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 129, 131,
+133, 135, 137, 138, 140, 142, 144, 146, 148, 149, 151, 153, 155, 157,
+158, 160, 162, 164, 166, 168, 169, 171, 173, 175, 177, 179, 180, 182,
+184, 186, 188, 189, 191, 193, 195, 197, 199, 200, 202, 204, 206, 208,
+209, 211, 213, 215 };
+
+static INT16 GR[] = { 127, 126, 125, 124, 123, 122, 121, 121, 120, 119,
+118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 108, 107, 106,
+105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 95, 94, 93, 92, 91,
+90, 89, 88, 87, 86, 85, 84, 83, 83, 82, 81, 80, 79, 78, 77, 76, 75,
+74, 73, 72, 71, 70, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59,
+58, 57, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 45, 44,
+43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 32, 31, 30, 29, 28,
+27, 26, 25, 24, 23, 22, 21, 20, 19, 19, 18, 17, 16, 15, 14, 13, 12,
+11, 10, 9, 8, 7, 6, 6, 5, 4, 3, 2, 1, 0, 0, -1, -2, -3, -4, -5, -5,
+-6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -18, -19,
+-20, -21, -22, -23, -24, -25, -26, -27, -28, -29, -30, -31, -31, -32,
+-33, -34, -35, -36, -37, -38, -39, -40, -41, -42, -43, -44, -44, -45,
+-46, -47, -48, -49, -50, -51, -52, -53, -54, -55, -56, -56, -57, -58,
+-59, -60, -61, -62, -63, -64, -65, -66, -67, -68, -69, -69, -70, -71,
+-72, -73, -74, -75, -76, -77, -78, -79, -80, -81, -82, -82, -83, -84,
+-85, -86, -87, -88, -89, -90, -91, -92, -93, -94, -94, -95, -96, -97,
+-98, -99, -100, -101, -102, -103, -104, -105, -106, -107, -107, -108 };
+
+#define R 0
+#define G 1
+#define B 2
+#define A 3
+
+#define YCC2RGB(rgb, y, cb, cr) {\
+ int l = L[y];\
+ int r = l + CR[cr];\
+ int g = l + GR[cr] + GB[cb];\
+ int b = l + CB[cb];\
+ rgb[0] = (r <= 0) ? 0 : (r >= 255) ? 255 : r;\
+ rgb[1] = (g <= 0) ? 0 : (g >= 255) ? 255 : g;\
+ rgb[2] = (b <= 0) ? 0 : (b >= 255) ? 255 : b;\
+}
+
+void
+ImagingUnpackYCC(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* PhotoYCC triplets */
+ for (i = 0; i < pixels; i++) {
+ YCC2RGB(out, in[0], in[1], in[2]);
+ out[A] = 255;
+ out += 4; in += 3;
+ }
+}
+
+void
+ImagingUnpackYCCA(UINT8* out, const UINT8* in, int pixels)
+{
+ int i;
+ /* PhotoYCC triplets plus premultiplied alpha */
+ for (i = 0; i < pixels; i++) {
+ /* Divide by alpha */
+ UINT8 rgb[3];
+ rgb[0] = (in[3] == 0) ? 0 : (((int) in[0] * 255) / in[3]);
+ rgb[1] = (in[3] == 0) ? 0 : (((int) in[1] * 255) / in[3]);
+ rgb[2] = (in[3] == 0) ? 0 : (((int) in[2] * 255) / in[3]);
+ /* Convert non-multiplied data to RGB */
+ YCC2RGB(out, rgb[0], rgb[1], rgb[2]);
+ out[A] = in[3];
+ out += 4; in += 4;
+ }
+}
diff --git a/Imaging/libImaging/XbmDecode.c b/Imaging/libImaging/XbmDecode.c
new file mode 100644
index 0000000..4819889
--- /dev/null
+++ b/Imaging/libImaging/XbmDecode.c
@@ -0,0 +1,81 @@
+/*
+ * The Python Imaging Library.
+ * $Id: XbmDecode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * decoder for XBM hex image data
+ *
+ * history:
+ * 96-04-13 fl Created
+ *
+ * Copyright (c) Fredrik Lundh 1996.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+#define HEX(v) ((v >= '0' && v <= '9') ? v - '0' :\
+ (v >= 'a' && v <= 'f') ? v - 'a' + 10 :\
+ (v >= 'A' && v <= 'F') ? v - 'A' + 10 : 0)
+
+int
+ImagingXbmDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ enum { BYTE = 1, SKIP };
+
+ UINT8* ptr;
+
+ if (!state->state)
+ state->state = SKIP;
+
+ ptr = buf;
+
+ for (;;) {
+
+ if (state->state == SKIP) {
+
+ /* Skip forward until next 'x' */
+
+ while (bytes > 0) {
+ if (*ptr == 'x')
+ break;
+ ptr++;
+ bytes--;
+ }
+
+ if (bytes == 0)
+ return ptr - buf;
+
+ state->state = BYTE;
+
+ }
+
+ if (bytes < 3)
+ return ptr - buf;
+
+ state->buffer[state->x] = (HEX(ptr[1])<<4) + HEX(ptr[2]);
+
+ if (++state->x >= state->bytes) {
+
+ /* Got a full line, unpack it */
+ state->shuffle((UINT8*) im->image[state->y], state->buffer,
+ state->xsize);
+
+ state->x = 0;
+
+ if (++state->y >= state->ysize) {
+ /* End of file (errcode = 0) */
+ return -1;
+ }
+ }
+
+ ptr += 3;
+ bytes -= 3;
+
+ state->state = SKIP;
+
+ }
+
+}
diff --git a/Imaging/libImaging/XbmEncode.c b/Imaging/libImaging/XbmEncode.c
new file mode 100644
index 0000000..8ca8ab1
--- /dev/null
+++ b/Imaging/libImaging/XbmEncode.c
@@ -0,0 +1,106 @@
+/*
+ * The Python Imaging Library.
+ * $Id: XbmEncode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * encoder for Xbm data
+ *
+ * history:
+ * 96-11-01 fl created
+ *
+ * Copyright (c) Fredrik Lundh 1996.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+
+int
+ImagingXbmEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ const char *hex = "0123456789abcdef";
+
+ UINT8* ptr = buf;
+ int i, n;
+
+ if (!state->state) {
+
+ /* 8 pixels are stored in no more than 6 bytes */
+ state->bytes = 6*(state->xsize+7)/8;
+
+ state->state = 1;
+
+ }
+
+ if (bytes < state->bytes) {
+ state->errcode = IMAGING_CODEC_MEMORY;
+ return 0;
+ }
+
+ ptr = buf;
+
+ while (bytes >= state->bytes) {
+
+ state->shuffle(state->buffer,
+ (UINT8*) im->image[state->y + state->yoff] +
+ state->xoff * im->pixelsize, state->xsize);
+
+ if (state->y < state->ysize-1) {
+
+ /* any line but the last */
+ for (n = 0; n < state->xsize; n += 8) {
+
+ i = state->buffer[n/8];
+
+ *ptr++ = '0';
+ *ptr++ = 'x';
+ *ptr++ = hex[(i>>4)&15];
+ *ptr++ = hex[i&15];
+ *ptr++ = ',';
+ bytes -= 5;
+
+ if (++state->count >= 79/5) {
+ *ptr++ = '\n';
+ bytes--;
+ state->count = 0;
+ }
+
+ }
+
+ state->y++;
+
+ } else {
+
+ /* last line */
+ for (n = 0; n < state->xsize; n += 8) {
+
+ i = state->buffer[n/8];
+
+ *ptr++ = '0';
+ *ptr++ = 'x';
+ *ptr++ = hex[(i>>4)&15];
+ *ptr++ = hex[i&15];
+
+ if (n < state->xsize-8) {
+ *ptr++ = ',';
+ if (++state->count >= 79/5) {
+ *ptr++ = '\n';
+ bytes--;
+ state->count = 0;
+ }
+ } else
+ *ptr++ = '\n';
+
+ bytes -= 5;
+
+ }
+
+ state->errcode = IMAGING_CODEC_END;
+ break;
+ }
+ }
+
+ return ptr - buf;
+}
diff --git a/Imaging/libImaging/Zip.h b/Imaging/libImaging/Zip.h
new file mode 100644
index 0000000..d306d7c
--- /dev/null
+++ b/Imaging/libImaging/Zip.h
@@ -0,0 +1,53 @@
+/*
+ * The Python Imaging Library.
+ * $Id: Zip.h 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * declarations for the ZIP codecs
+ *
+ * Copyright (c) Fredrik Lundh 1996.
+ */
+
+
+#include "zlib.h"
+
+
+/* modes */
+#define ZIP_PNG 0 /* continuous, filtered image data */
+#define ZIP_PNG_PALETTE 1 /* non-continuous data, disable filtering */
+#define ZIP_TIFF_PREDICTOR 2 /* TIFF, with predictor */
+#define ZIP_TIFF 3 /* TIFF, without predictor */
+
+
+typedef struct {
+
+ /* CONFIGURATION */
+
+ /* Codec mode */
+ int mode;
+
+ /* Optimize (max compression) SLOW!!! */
+ int optimize;
+
+ /* Predefined dictionary (experimental) */
+ char* dictionary;
+ int dictionary_size;
+
+ /* PRIVATE CONTEXT (set by decoder/encoder) */
+
+ z_stream z_stream; /* (de)compression stream */
+
+ UINT8* previous; /* previous line (allocated) */
+
+ int last_output; /* # bytes last output by inflate */
+
+ /* Compressor specific stuff */
+ UINT8* prior; /* filter storage (allocated) */
+ UINT8* up;
+ UINT8* average;
+ UINT8* paeth;
+
+ UINT8* output; /* output data */
+
+ int prefix; /* size of filter prefix (0 for TIFF data) */
+
+} ZIPSTATE;
diff --git a/Imaging/libImaging/ZipDecode.c b/Imaging/libImaging/ZipDecode.c
new file mode 100644
index 0000000..71e0a73
--- /dev/null
+++ b/Imaging/libImaging/ZipDecode.c
@@ -0,0 +1,208 @@
+/*
+ * The Python Imaging Library.
+ * $Id: ZipDecode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * decoder for ZIP (deflated) image data.
+ *
+ * history:
+ * 1996-12-14 fl Created (for PNG)
+ * 1997-01-15 fl Prepared to read TIFF/ZIP
+ * 2001-11-19 fl PNG incomplete read patch (from Bernhard Herzog)
+ *
+ * Copyright (c) Fredrik Lundh 1996.
+ * Copyright (c) Secret Labs AB 1997-2001.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+#ifdef HAVE_LIBZ
+
+#include "Zip.h"
+
+
+/* -------------------------------------------------------------------- */
+/* Decoder */
+/* -------------------------------------------------------------------- */
+
+int
+ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ ZIPSTATE* context = (ZIPSTATE*) state->context;
+ int err;
+ int n;
+ UINT8* ptr;
+ int i, bpp;
+
+ if (!state->state) {
+
+ /* Initialization */
+ if (context->mode == ZIP_PNG || context->mode == ZIP_PNG_PALETTE)
+ context->prefix = 1; /* PNG */
+
+ /* Expand standard buffer to make room for the (optional) filter
+ prefix, and allocate a buffer to hold the previous line */
+ free(state->buffer);
+ state->buffer = (UINT8*) malloc(state->bytes+1);
+ context->previous = (UINT8*) malloc(state->bytes+1);
+ if (!state->buffer || !context->previous) {
+ state->errcode = IMAGING_CODEC_MEMORY;
+ return -1;
+ }
+
+ context->last_output = 0;
+
+ /* Initialize to black */
+ memset(context->previous, 0, state->bytes+1);
+
+ /* Setup decompression context */
+ context->z_stream.zalloc = (alloc_func)0;
+ context->z_stream.zfree = (free_func)0;
+ context->z_stream.opaque = (voidpf)0;
+
+ err = inflateInit(&context->z_stream);
+ if (err < 0) {
+ state->errcode = IMAGING_CODEC_CONFIG;
+ return -1;
+ }
+
+ /* Ready to decode */
+ state->state = 1;
+
+ }
+
+ /* Setup the source buffer */
+ context->z_stream.next_in = buf;
+ context->z_stream.avail_in = bytes;
+
+ /* Decompress what we've got this far */
+ while (context->z_stream.avail_in > 0) {
+
+ context->z_stream.next_out = state->buffer + context->last_output;
+ context->z_stream.avail_out =
+ state->bytes + context->prefix - context->last_output;
+
+ err = inflate(&context->z_stream, Z_NO_FLUSH);
+
+ if (err < 0) {
+ /* Something went wrong inside the compression library */
+ if (err == Z_DATA_ERROR)
+ state->errcode = IMAGING_CODEC_BROKEN;
+ else if (err == Z_MEM_ERROR)
+ state->errcode = IMAGING_CODEC_MEMORY;
+ else
+ state->errcode = IMAGING_CODEC_CONFIG;
+ free(context->previous);
+ inflateEnd(&context->z_stream);
+ return -1;
+ }
+
+ n = state->bytes + context->prefix - context->z_stream.avail_out;
+
+ if (n < state->bytes + context->prefix) {
+ context->last_output = n;
+ break; /* need more input data */
+ }
+
+ /* Apply predictor */
+ switch (context->mode) {
+ case ZIP_PNG:
+ switch (state->buffer[0]) {
+ case 0:
+ break;
+ case 1:
+ /* prior */
+ bpp = (state->bits + 7) / 8;
+ for (i = bpp+1; i <= state->bytes; i++)
+ state->buffer[i] += state->buffer[i-bpp];
+ break;
+ case 2:
+ /* up */
+ for (i = 1; i <= state->bytes; i++)
+ state->buffer[i] += context->previous[i];
+ break;
+ case 3:
+ /* average */
+ bpp = (state->bits + 7) / 8;
+ for (i = 1; i <= bpp; i++)
+ state->buffer[i] += context->previous[i]/2;
+ for (; i <= state->bytes; i++)
+ state->buffer[i] +=
+ (state->buffer[i-bpp] + context->previous[i])/2;
+ break;
+ case 4:
+ /* paeth filtering */
+ bpp = (state->bits + 7) / 8;
+ for (i = 1; i <= bpp; i++)
+ state->buffer[i] += context->previous[i];
+ for (; i <= state->bytes; i++) {
+ int a, b, c;
+ int pa, pb, pc;
+
+ /* fetch pixels */
+ a = state->buffer[i-bpp];
+ b = context->previous[i];
+ c = context->previous[i-bpp];
+
+ /* distances to surrounding pixels */
+ pa = abs(b - c);
+ pb = abs(a - c);
+ pc = abs(a + b - 2*c);
+
+ /* pick predictor with the shortest distance */
+ state->buffer[i] +=
+ (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
+
+ }
+ break;
+ default:
+ state->errcode = IMAGING_CODEC_UNKNOWN;
+ free(context->previous);
+ inflateEnd(&context->z_stream);
+ return -1;
+ }
+ break;
+ case ZIP_TIFF_PREDICTOR:
+ bpp = (state->bits + 7) / 8;
+ for (i = bpp+1; i <= state->bytes; i++)
+ state->buffer[i] += state->buffer[i-bpp];
+ break;
+ }
+
+ /* Stuff data into the image */
+ state->shuffle((UINT8*) im->image[state->y + state->yoff] +
+ state->xoff * im->pixelsize,
+ state->buffer + context->prefix,
+ state->xsize);
+
+ state->y++;
+
+ /* all inflate output has been consumed */
+ context->last_output = 0;
+
+ if (state->y >= state->ysize || err == Z_STREAM_END) {
+
+ /* The image and the data should end simultaneously */
+ /* if (state->y < state->ysize || err != Z_STREAM_END)
+ state->errcode = IMAGING_CODEC_BROKEN; */
+
+ free(context->previous);
+ inflateEnd(&context->z_stream);
+ return -1; /* end of file (errcode=0) */
+
+ }
+
+ /* Swap buffer pointers */
+ ptr = state->buffer;
+ state->buffer = context->previous;
+ context->previous = ptr;
+
+ }
+
+ return bytes; /* consumed all of it */
+
+}
+
+#endif
diff --git a/Imaging/libImaging/ZipEncode.c b/Imaging/libImaging/ZipEncode.c
new file mode 100644
index 0000000..11e000c
--- /dev/null
+++ b/Imaging/libImaging/ZipEncode.c
@@ -0,0 +1,314 @@
+/*
+ * The Python Imaging Library.
+ * $Id: ZipEncode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * coder for ZIP (deflated) image data
+ *
+ * History:
+ * 96-12-29 fl created
+ * 96-12-30 fl adaptive filter selection, encoder tuning
+ *
+ * Copyright (c) Fredrik Lundh 1996.
+ * Copyright (c) Secret Labs AB 1997.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+#ifdef HAVE_LIBZ
+
+#include "Zip.h"
+
+int
+ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ ZIPSTATE* context = (ZIPSTATE*) state->context;
+ int err;
+ UINT8* ptr;
+ int i, bpp, s, sum;
+
+ if (!state->state) {
+
+ /* Initialization */
+
+ /* Valid modes are ZIP_PNG, ZIP_PNG_PALETTE, and ZIP_TIFF */
+
+ /* Expand standard buffer to make room for the filter selector,
+ and allocate filter buffers */
+ free(state->buffer);
+ state->buffer = (UINT8*) malloc(state->bytes+1);
+ context->previous = (UINT8*) malloc(state->bytes+1);
+ context->prior = (UINT8*) malloc(state->bytes+1);
+ context->up = (UINT8*) malloc(state->bytes+1);
+ context->average = (UINT8*) malloc(state->bytes+1);
+ context->paeth = (UINT8*) malloc(state->bytes+1);
+ if (!state->buffer || !context->previous || !context->prior ||
+ !context->up || !context->average || !context->paeth) {
+ free(context->paeth);
+ free(context->average);
+ free(context->up);
+ free(context->prior);
+ free(context->previous);
+ state->errcode = IMAGING_CODEC_MEMORY;
+ return -1;
+ }
+
+ /* Initalise filter buffers */
+ state->buffer[0] = 0;
+ context->prior[0] = 1;
+ context->up[0] = 2;
+ context->average[0] = 3;
+ context->paeth[0] = 4;
+
+ /* Initialise previous buffer to black */
+ memset(context->previous, 0, state->bytes+1);
+
+ /* Setup compression context */
+ context->z_stream.zalloc = (alloc_func)0;
+ context->z_stream.zfree = (free_func)0;
+ context->z_stream.opaque = (voidpf)0;
+
+ err = deflateInit2(&context->z_stream,
+ /* compression level */
+ (context->optimize) ? Z_BEST_COMPRESSION
+ : Z_DEFAULT_COMPRESSION,
+ /* compression method */
+ Z_DEFLATED,
+ /* compression memory resources */
+ 15, 9,
+ /* compression strategy (image data are filtered)*/
+ (context->mode == ZIP_PNG) ? Z_FILTERED
+ : Z_DEFAULT_STRATEGY);
+ if (err < 0) {
+ state->errcode = IMAGING_CODEC_CONFIG;
+ return -1;
+ }
+
+ if (context->dictionary && context->dictionary_size > 0) {
+ err = deflateSetDictionary(&context->z_stream, (unsigned char *)context->dictionary,
+ context->dictionary_size);
+ if (err < 0) {
+ state->errcode = IMAGING_CODEC_CONFIG;
+ return -1;
+ }
+ }
+
+ /* Ready to decode */
+ state->state = 1;
+
+ }
+
+ /* Setup the destination buffer */
+ context->z_stream.next_out = buf;
+ context->z_stream.avail_out = bytes;
+
+ for (;;) {
+
+ switch (state->state) {
+
+ case 1:
+
+ /* Compress image data */
+ while (context->z_stream.avail_out > 0) {
+
+ if (state->y >= state->ysize) {
+ /* End of image; now flush compressor buffers */
+ state->state = 2;
+ break;
+
+ }
+
+ /* Stuff image data into the compressor */
+ state->shuffle(state->buffer+1,
+ (UINT8*) im->image[state->y + state->yoff] +
+ state->xoff * im->pixelsize,
+ state->xsize);
+
+ state->y++;
+
+ context->output = state->buffer;
+
+ if (context->mode == ZIP_PNG) {
+
+ /* Filter the image data. For each line, select
+ the filter that gives the least total distance
+ from zero for the filtered data (taken from
+ LIBPNG) */
+
+ bpp = (state->bits + 7) / 8;
+
+ /* 0. No filter */
+ for (i = 1, sum = 0; i <= state->bytes; i++) {
+ UINT8 v = state->buffer[i];
+ sum += (v < 128) ? v : 256 - v;
+ }
+
+ /* 2. Up. We'll test this first to save time when
+ an image line is identical to the one above. */
+ if (sum > 0) {
+ for (i = 1, s = 0; i <= state->bytes; i++) {
+ UINT8 v = state->buffer[i] - context->previous[i];
+ context->up[i] = v;
+ s += (v < 128) ? v : 256 - v;
+ }
+ if (s < sum) {
+ context->output = context->up;
+ sum = s; /* 0 if line was duplicated */
+ }
+ }
+
+ /* 1. Prior */
+ if (sum > 0) {
+ for (i = 1, s = 0; i <= bpp; i++) {
+ UINT8 v = state->buffer[i];
+ context->prior[i] = v;
+ s += (v < 128) ? v : 256 - v;
+ }
+ for (; i <= state->bytes; i++) {
+ UINT8 v = state->buffer[i] - state->buffer[i-bpp];
+ context->prior[i] = v;
+ s += (v < 128) ? v : 256 - v;
+ }
+ if (s < sum) {
+ context->output = context->prior;
+ sum = s; /* 0 if line is solid */
+ }
+ }
+
+ /* 3. Average (not very common in real-life images,
+ so its only used with the optimize option) */
+ if (context->optimize && sum > 0) {
+ for (i = 1, s = 0; i <= bpp; i++) {
+ UINT8 v = state->buffer[i] - context->previous[i]/2;
+ context->average[i] = v;
+ s += (v < 128) ? v : 256 - v;
+ }
+ for (; i <= state->bytes; i++) {
+ UINT8 v = state->buffer[i] -
+ (state->buffer[i-bpp] + context->previous[i])/2;
+ context->average[i] = v;
+ s += (v < 128) ? v : 256 - v;
+ }
+ if (s < sum) {
+ context->output = context->average;
+ sum = s;
+ }
+ }
+
+ /* 4. Paeth */
+ if (sum > 0) {
+ for (i = 1, s = 0; i <= bpp; i++) {
+ UINT8 v = state->buffer[i] - context->previous[i];
+ context->paeth[i] = v;
+ s += (v < 128) ? v : 256 - v;
+ }
+ for (; i <= state->bytes; i++) {
+ UINT8 v;
+ int a, b, c;
+ int pa, pb, pc;
+
+ /* fetch pixels */
+ a = state->buffer[i-bpp];
+ b = context->previous[i];
+ c = context->previous[i-bpp];
+
+ /* distances to surrounding pixels */
+ pa = abs(b - c);
+ pb = abs(a - c);
+ pc = abs(a + b - 2*c);
+
+ /* pick predictor with the shortest distance */
+ v = state->buffer[i] -
+ ((pa <= pb && pa <= pc) ? a :
+ (pb <= pc) ? b : c);
+ context->paeth[i] = v;
+ s += (v < 128) ? v : 256 - v;
+ }
+ if (s < sum) {
+ context->output = context->paeth;
+ sum = s;
+ }
+ }
+ }
+
+ /* Compress this line */
+ context->z_stream.next_in = context->output;
+ context->z_stream.avail_in = state->bytes+1;
+
+ /* err = deflate(&context->z_stream, Z_NO_FLUSH); */
+
+ /* FIXME: temporary workaround for problem with recent
+ versions of zlib -- 990709/fl */
+
+ err = deflate(&context->z_stream, Z_SYNC_FLUSH);
+
+ if (err < 0) {
+ /* Something went wrong inside the compression library */
+ if (err == Z_DATA_ERROR)
+ state->errcode = IMAGING_CODEC_BROKEN;
+ else if (err == Z_MEM_ERROR)
+ state->errcode = IMAGING_CODEC_MEMORY;
+ else
+ state->errcode = IMAGING_CODEC_CONFIG;
+ free(context->paeth);
+ free(context->average);
+ free(context->up);
+ free(context->prior);
+ free(context->previous);
+ deflateEnd(&context->z_stream);
+ return -1;
+ }
+
+ /* Swap buffer pointers */
+ ptr = state->buffer;
+ state->buffer = context->previous;
+ context->previous = ptr;
+
+ }
+
+ if (context->z_stream.avail_out == 0)
+ break; /* Buffer full */
+
+ case 2:
+
+ /* End of image data; flush compressor buffers */
+
+ while (context->z_stream.avail_out > 0) {
+
+ err = deflate(&context->z_stream, Z_FINISH);
+
+ if (err == Z_STREAM_END) {
+
+ free(context->paeth);
+ free(context->average);
+ free(context->up);
+ free(context->prior);
+ free(context->previous);
+
+ deflateEnd(&context->z_stream);
+
+ state->errcode = IMAGING_CODEC_END;
+
+ break;
+ }
+
+ if (context->z_stream.avail_out == 0)
+ break; /* Buffer full */
+
+ }
+
+ }
+
+ return bytes - context->z_stream.avail_out;
+
+ }
+
+ /* Should never ever arrive here... */
+
+ state->errcode = IMAGING_CODEC_CONFIG;
+ return -1;
+}
+
+#endif
diff --git a/Imaging/map.c b/Imaging/map.c
new file mode 100644
index 0000000..19f2b8a
--- /dev/null
+++ b/Imaging/map.c
@@ -0,0 +1,382 @@
+/*
+ * The Python Imaging Library.
+ * $Id: map.c 2751 2006-06-18 19:50:45Z fredrik $
+ *
+ * standard memory mapping interface for the Imaging library
+ *
+ * history:
+ * 1998-03-05 fl added Win32 read mapping
+ * 1999-02-06 fl added "I;16" support
+ * 2003-04-21 fl added PyImaging_MapBuffer primitive
+ *
+ * Copyright (c) 1998-2003 by Secret Labs AB.
+ * Copyright (c) 2003 by Fredrik Lundh.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+/*
+ * FIXME: should move the memory mapping primitives into libImaging!
+ */
+
+#include "Python.h"
+
+#if PY_VERSION_HEX < 0x01060000
+#define PyObject_New PyObject_NEW
+#define PyObject_Del PyMem_DEL
+#endif
+
+#include "Imaging.h"
+
+#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#ifdef __GNUC__
+#undef INT32
+#undef INT64
+#undef UINT32
+#endif
+#include "windows.h"
+#endif
+
+/* -------------------------------------------------------------------- */
+/* Standard mapper */
+
+typedef struct {
+ PyObject_HEAD
+ char* base;
+ int size;
+ int offset;
+#ifdef WIN32
+ HANDLE hFile;
+ HANDLE hMap;
+#endif
+} ImagingMapperObject;
+
+staticforward PyTypeObject ImagingMapperType;
+
+ImagingMapperObject*
+PyImaging_MapperNew(const char* filename, int readonly)
+{
+ ImagingMapperObject *mapper;
+
+ ImagingMapperType.ob_type = &PyType_Type;
+
+ mapper = PyObject_New(ImagingMapperObject, &ImagingMapperType);
+ if (mapper == NULL)
+ return NULL;
+
+ mapper->base = NULL;
+ mapper->size = mapper->offset = 0;
+
+#ifdef WIN32
+ mapper->hFile = (HANDLE)-1;
+ mapper->hMap = (HANDLE)-1;
+
+ /* FIXME: currently supports readonly mappings only */
+ mapper->hFile = CreateFile(
+ filename,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (mapper->hFile == (HANDLE)-1) {
+ PyErr_SetString(PyExc_IOError, "cannot open file");
+ PyObject_Del(mapper);
+ return NULL;
+ }
+
+ mapper->hMap = CreateFileMapping(
+ mapper->hFile, NULL,
+ PAGE_READONLY,
+ 0, 0, NULL);
+ if (mapper->hMap == (HANDLE)-1) {
+ CloseHandle(mapper->hFile);
+ PyErr_SetString(PyExc_IOError, "cannot map file");
+ PyObject_Del(mapper);
+ return NULL;
+ }
+
+ mapper->base = (char*) MapViewOfFile(
+ mapper->hMap,
+ FILE_MAP_READ,
+ 0, 0, 0);
+
+ mapper->size = GetFileSize(mapper->hFile, 0);
+#endif
+
+ return mapper;
+}
+
+static void
+mapping_dealloc(ImagingMapperObject* mapper)
+{
+#ifdef WIN32
+ if (mapper->base != 0)
+ UnmapViewOfFile(mapper->base);
+ if (mapper->hMap != (HANDLE)-1)
+ CloseHandle(mapper->hMap);
+ if (mapper->hFile != (HANDLE)-1)
+ CloseHandle(mapper->hFile);
+ mapper->base = 0;
+ mapper->hMap = mapper->hFile = (HANDLE)-1;
+#endif
+ PyObject_Del(mapper);
+}
+
+/* -------------------------------------------------------------------- */
+/* standard file operations */
+
+static PyObject*
+mapping_read(ImagingMapperObject* mapper, PyObject* args)
+{
+ PyObject* buf;
+
+ int size = -1;
+ if (!PyArg_ParseTuple(args, "|i", &size))
+ return NULL;
+
+ /* check size */
+ if (size < 0 || mapper->offset + size > mapper->size)
+ size = mapper->size - mapper->offset;
+ if (size < 0)
+ size = 0;
+
+ buf = PyString_FromStringAndSize(NULL, size);
+ if (!buf)
+ return NULL;
+
+ if (size > 0) {
+ memcpy(PyString_AsString(buf), mapper->base + mapper->offset, size);
+ mapper->offset += size;
+ }
+
+ return buf;
+}
+
+static PyObject*
+mapping_seek(ImagingMapperObject* mapper, PyObject* args)
+{
+ int offset;
+ int whence = 0;
+ if (!PyArg_ParseTuple(args, "i|i", &offset, &whence))
+ return NULL;
+
+ switch (whence) {
+ case 0: /* SEEK_SET */
+ mapper->offset = offset;
+ break;
+ case 1: /* SEEK_CUR */
+ mapper->offset += offset;
+ break;
+ case 2: /* SEEK_END */
+ mapper->offset = mapper->size + offset;
+ break;
+ default:
+ /* FIXME: raise ValueError? */
+ break;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/* -------------------------------------------------------------------- */
+/* map entire image */
+
+extern PyObject*PyImagingNew(Imaging im);
+
+static void
+ImagingDestroyMap(Imaging im)
+{
+ return; /* nothing to do! */
+}
+
+static PyObject*
+mapping_readimage(ImagingMapperObject* mapper, PyObject* args)
+{
+ int y, size;
+ Imaging im;
+
+ char* mode;
+ int xsize;
+ int ysize;
+ int stride;
+ int orientation;
+ if (!PyArg_ParseTuple(args, "s(ii)ii", &mode, &xsize, &ysize,
+ &stride, &orientation))
+ return NULL;
+
+ if (stride <= 0) {
+ /* FIXME: maybe we should call ImagingNewPrologue instead */
+ if (!strcmp(mode, "L") || !strcmp(mode, "P"))
+ stride = xsize;
+ else if (!strcmp(mode, "I;16") || !strcmp(mode, "I;16B"))
+ stride = xsize * 2;
+ else
+ stride = xsize * 4;
+ }
+
+ size = ysize * stride;
+
+ if (mapper->offset + size > mapper->size) {
+ PyErr_SetString(PyExc_IOError, "image file truncated");
+ return NULL;
+ }
+
+ im = ImagingNewPrologue(mode, xsize, ysize);
+ if (!im)
+ return NULL;
+
+ /* setup file pointers */
+ if (orientation > 0)
+ for (y = 0; y < ysize; y++)
+ im->image[y] = mapper->base + mapper->offset + y * stride;
+ else
+ for (y = 0; y < ysize; y++)
+ im->image[ysize-y-1] = mapper->base + mapper->offset + y * stride;
+
+ im->destroy = ImagingDestroyMap;
+
+ if (!ImagingNewEpilogue(im))
+ return NULL;
+
+ mapper->offset += size;
+
+ return PyImagingNew(im);
+}
+
+static struct PyMethodDef methods[] = {
+ /* standard file interface */
+ {"read", (PyCFunction)mapping_read, 1},
+ {"seek", (PyCFunction)mapping_seek, 1},
+ /* extensions */
+ {"readimage", (PyCFunction)mapping_readimage, 1},
+ {NULL, NULL} /* sentinel */
+};
+
+static PyObject*
+mapping_getattr(ImagingMapperObject* self, char* name)
+{
+ return Py_FindMethod(methods, (PyObject*) self, name);
+}
+
+statichere PyTypeObject ImagingMapperType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "ImagingMapper", /*tp_name*/
+ sizeof(ImagingMapperObject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor)mapping_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ (getattrfunc)mapping_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_hash*/
+};
+
+PyObject*
+PyImaging_Mapper(PyObject* self, PyObject* args)
+{
+ char* filename;
+ if (!PyArg_ParseTuple(args, "s", &filename))
+ return NULL;
+
+ return (PyObject*) PyImaging_MapperNew(filename, 1);
+}
+
+/* -------------------------------------------------------------------- */
+/* Buffer mapper */
+
+typedef struct ImagingBufferInstance {
+ struct ImagingMemoryInstance im;
+ PyObject* target;
+} ImagingBufferInstance;
+
+static void
+mapping_destroy_buffer(Imaging im)
+{
+ ImagingBufferInstance* buffer = (ImagingBufferInstance*) im;
+
+ Py_XDECREF(buffer->target);
+}
+
+PyObject*
+PyImaging_MapBuffer(PyObject* self, PyObject* args)
+{
+ int y, size;
+ Imaging im;
+ PyBufferProcs *buffer;
+ char* ptr;
+ int bytes;
+
+ PyObject* target;
+ char* mode;
+ char* codec;
+ PyObject* bbox;
+ int offset;
+ int xsize, ysize;
+ int stride;
+ int ystep;
+
+ if (!PyArg_ParseTuple(args, "O(ii)sOi(sii)", &target, &xsize, &ysize,
+ &codec, &bbox, &offset, &mode, &stride, &ystep))
+ return NULL;
+
+ /* check target object */
+ buffer = target->ob_type->tp_as_buffer;
+ if (!buffer || !buffer->bf_getreadbuffer || !buffer->bf_getsegcount ||
+ buffer->bf_getsegcount(target, NULL) != 1) {
+ PyErr_SetString(PyExc_TypeError, "expected string or buffer");
+ return NULL;
+ }
+
+ if (stride <= 0) {
+ if (!strcmp(mode, "L") || !strcmp(mode, "P"))
+ stride = xsize;
+ else if (!strcmp(mode, "I;16") || !strcmp(mode, "I;16B"))
+ stride = xsize * 2;
+ else
+ stride = xsize * 4;
+ }
+
+ size = ysize * stride;
+
+ /* check buffer size */
+ bytes = buffer->bf_getreadbuffer(target, 0, (void**) &ptr);
+ if (bytes < 0) {
+ PyErr_SetString(PyExc_ValueError, "buffer has negative size");
+ return NULL;
+ }
+ if (offset + size > bytes) {
+ PyErr_SetString(PyExc_ValueError, "buffer is not large enough");
+ return NULL;
+ }
+
+ im = ImagingNewPrologueSubtype(
+ mode, xsize, ysize, sizeof(ImagingBufferInstance)
+ );
+ if (!im)
+ return NULL;
+
+ /* setup file pointers */
+ if (ystep > 0)
+ for (y = 0; y < ysize; y++)
+ im->image[y] = ptr + offset + y * stride;
+ else
+ for (y = 0; y < ysize; y++)
+ im->image[ysize-y-1] = ptr + offset + y * stride;
+
+ im->destroy = mapping_destroy_buffer;
+
+ Py_INCREF(target);
+ ((ImagingBufferInstance*) im)->target = target;
+
+ if (!ImagingNewEpilogue(im))
+ return NULL;
+
+ return PyImagingNew(im);
+}
+
diff --git a/Imaging/outline.c b/Imaging/outline.c
new file mode 100644
index 0000000..351e6e5
--- /dev/null
+++ b/Imaging/outline.c
@@ -0,0 +1,180 @@
+/*
+ * THIS IS WORK IN PROGRESS.
+ *
+ * The Python Imaging Library.
+ * $Id: outline.c 2751 2006-06-18 19:50:45Z fredrik $
+ *
+ * "arrow" outline stuff. the contents of this module
+ * will be merged with the path module and the rest of
+ * the arrow graphics package, but not before PIL 1.1.
+ * use at your own risk.
+ *
+ * history:
+ * 99-01-10 fl Added to PIL (experimental)
+ *
+ * Copyright (c) Secret Labs AB 1999.
+ * Copyright (c) Fredrik Lundh 1999.
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+#include "Python.h"
+
+#if PY_VERSION_HEX < 0x01060000
+#define PyObject_New PyObject_NEW
+#define PyObject_Del PyMem_DEL
+#endif
+
+#include "Imaging.h"
+
+
+/* -------------------------------------------------------------------- */
+/* Class */
+
+typedef struct {
+ PyObject_HEAD
+ ImagingOutline outline;
+} OutlineObject;
+
+staticforward PyTypeObject OutlineType;
+
+#define PyOutline_Check(op) ((op)->ob_type == &OutlineType)
+
+static OutlineObject*
+_outline_new(void)
+{
+ OutlineObject *self;
+
+ self = PyObject_New(OutlineObject, &OutlineType);
+ if (self == NULL)
+ return NULL;
+
+ self->outline = ImagingOutlineNew();
+
+ return self;
+}
+
+static void
+_outline_dealloc(OutlineObject* self)
+{
+ ImagingOutlineDelete(self->outline);
+ PyObject_Del(self);
+}
+
+ImagingOutline
+PyOutline_AsOutline(PyObject* outline)
+{
+ if (PyOutline_Check(outline))
+ return ((OutlineObject*) outline)->outline;
+
+ return NULL;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Factories */
+
+PyObject*
+PyOutline_Create(PyObject* self, PyObject* args)
+{
+ if (!PyArg_ParseTuple(args, ":outline"))
+ return NULL;
+
+ return (PyObject*) _outline_new();
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Methods */
+
+static PyObject*
+_outline_move(OutlineObject* self, PyObject* args)
+{
+ float x0, y0;
+ if (!PyArg_ParseTuple(args, "ff", &x0, &y0))
+ return NULL;
+
+ ImagingOutlineMove(self->outline, x0, y0);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_outline_line(OutlineObject* self, PyObject* args)
+{
+ float x1, y1;
+ if (!PyArg_ParseTuple(args, "ff", &x1, &y1))
+ return NULL;
+
+ ImagingOutlineLine(self->outline, x1, y1);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_outline_curve(OutlineObject* self, PyObject* args)
+{
+ float x1, y1, x2, y2, x3, y3;
+ if (!PyArg_ParseTuple(args, "ffffff", &x1, &y1, &x2, &y2, &x3, &y3))
+ return NULL;
+
+ ImagingOutlineCurve(self->outline, x1, y1, x2, y2, x3, y3);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_outline_close(OutlineObject* self, PyObject* args)
+{
+ if (!PyArg_ParseTuple(args, ":close"))
+ return NULL;
+
+ ImagingOutlineClose(self->outline);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject*
+_outline_transform(OutlineObject* self, PyObject* args)
+{
+ double a[6];
+ if (!PyArg_ParseTuple(args, "(dddddd)", a+0, a+1, a+2, a+3, a+4, a+5))
+ return NULL;
+
+ ImagingOutlineTransform(self->outline, a);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static struct PyMethodDef _outline_methods[] = {
+ {"line", (PyCFunction)_outline_line, 1},
+ {"curve", (PyCFunction)_outline_curve, 1},
+ {"move", (PyCFunction)_outline_move, 1},
+ {"close", (PyCFunction)_outline_close, 1},
+ {"transform", (PyCFunction)_outline_transform, 1},
+ {NULL, NULL} /* sentinel */
+};
+
+static PyObject*
+_outline_getattr(OutlineObject* self, char* name)
+{
+ return Py_FindMethod(_outline_methods, (PyObject*) self, name);
+}
+
+statichere PyTypeObject OutlineType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "Outline", /*tp_name*/
+ sizeof(OutlineObject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor)_outline_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ (getattrfunc)_outline_getattr, /*tp_getattr*/
+ 0 /*tp_setattr*/
+};
diff --git a/Imaging/path.c b/Imaging/path.c
new file mode 100644
index 0000000..2810988
--- /dev/null
+++ b/Imaging/path.c
@@ -0,0 +1,585 @@
+/*
+ * The Python Imaging Library.
+ * $Id: path.c 2935 2006-12-03 12:20:39Z fredrik $
+ *
+ * 2D path utilities
+ *
+ * history:
+ * 1996-11-04 fl Added to PIL (incomplete)
+ * 1996-11-05 fl Added sequence semantics
+ * 1997-02-28 fl Fixed getbbox
+ * 1997-06-12 fl Added id attribute
+ * 1997-06-14 fl Added slicing and setitem
+ * 1998-12-29 fl Improved sequence handling (from Richard Jones)
+ * 1999-01-10 fl Fixed IndexError test for 1.5 (from Fred Drake)
+ * 2000-10-12 fl Added special cases for tuples and lists
+ * 2002-10-27 fl Added clipping boilerplate
+ * 2004-09-19 fl Added tolist(flat) variant
+ * 2005-05-06 fl Added buffer interface support to path constructor
+ *
+ * notes:
+ * FIXME: fill in remaining slots in the sequence api
+ *
+ * Copyright (c) 1997-2005 by Secret Labs AB
+ * Copyright (c) 1997-2005 by Fredrik Lundh
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "Python.h"
+
+#include <math.h>
+
+#if PY_VERSION_HEX < 0x01060000
+#define PyObject_New PyObject_NEW
+#define PyObject_Del PyMem_DEL
+#endif
+
+#if PY_VERSION_HEX < 0x02050000
+#define ssizeargfunc intargfunc
+#define ssizessizeargfunc intintargfunc
+#define ssizeobjargproc intobjargproc
+#define ssizessizeobjargproc intintobjargproc
+#endif
+
+/* -------------------------------------------------------------------- */
+/* Class */
+/* -------------------------------------------------------------------- */
+
+typedef struct {
+ PyObject_HEAD
+ int count;
+ double *xy;
+ int index; /* temporary use, e.g. in decimate */
+} PyPathObject;
+
+staticforward PyTypeObject PyPathType;
+
+static double*
+alloc_array(int count)
+{
+ double* xy;
+ if (count < 0) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ xy = malloc(2 * count * sizeof(double) + 1);
+ if (!xy)
+ PyErr_NoMemory();
+ return xy;
+}
+
+static PyPathObject*
+path_new(int count, double* xy, int duplicate)
+{
+ PyPathObject *path;
+
+ if (duplicate) {
+ /* duplicate path */
+ double* p = alloc_array(count);
+ if (!p)
+ return NULL;
+ memcpy(p, xy, count * 2 * sizeof(double));
+ xy = p;
+ }
+
+ path = PyObject_New(PyPathObject, &PyPathType);
+ if (path == NULL)
+ return NULL;
+
+ path->count = count;
+ path->xy = xy;
+
+ return path;
+}
+
+static void
+path_dealloc(PyPathObject* path)
+{
+ free(path->xy);
+ PyObject_Del(path);
+}
+
+/* -------------------------------------------------------------------- */
+/* Helpers */
+/* -------------------------------------------------------------------- */
+
+#define PyPath_Check(op) ((op)->ob_type == &PyPathType)
+
+int
+PyPath_Flatten(PyObject* data, double **pxy)
+{
+ int i, j, n;
+ double *xy;
+ PyBufferProcs *buffer;
+
+ if (PyPath_Check(data)) {
+ /* This was another path object. */
+ PyPathObject *path = (PyPathObject*) data;
+ xy = alloc_array(path->count);
+ if (!xy)
+ return -1;
+ memcpy(xy, path->xy, 2 * path->count * sizeof(double));
+ *pxy = xy;
+ return path->count;
+ }
+
+ buffer = data->ob_type->tp_as_buffer;
+ if (buffer && buffer->bf_getreadbuffer && buffer->bf_getsegcount &&
+ buffer->bf_getsegcount(data, NULL) == 1) {
+ /* Assume the buffer contains floats */
+ float* ptr;
+ int n = buffer->bf_getreadbuffer(data, 0, (void**) &ptr);
+ n /= 2 * sizeof(float);
+ xy = alloc_array(n);
+ if (!xy)
+ return -1;
+ for (i = 0; i < n+n; i++)
+ xy[i] = ptr[i];
+ *pxy = xy;
+ return n;
+ }
+
+ if (!PySequence_Check(data)) {
+ PyErr_SetString(PyExc_TypeError, "argument must be sequence");
+ return -1;
+ }
+
+ j = 0;
+ n = PyObject_Length(data);
+ /* Just in case __len__ breaks (or doesn't exist) */
+ if (PyErr_Occurred())
+ return -1;
+
+ /* Allocate for worst case */
+ xy = alloc_array(n);
+ if (!xy)
+ return -1;
+
+ /* Copy table to path array */
+ if (PyList_Check(data)) {
+ for (i = 0; i < n; i++) {
+ double x, y;
+ PyObject *op = PyList_GET_ITEM(data, i);
+ if (PyFloat_Check(op))
+ xy[j++] = PyFloat_AS_DOUBLE(op);
+ else if (PyInt_Check(op))
+ xy[j++] = (float) PyInt_AS_LONG(op);
+ else if (PyNumber_Check(op))
+ xy[j++] = PyFloat_AsDouble(op);
+ else if (PyArg_ParseTuple(op, "dd", &x, &y)) {
+ xy[j++] = x;
+ xy[j++] = y;
+ } else {
+ free(xy);
+ return -1;
+ }
+ }
+ } else if (PyTuple_Check(data)) {
+ for (i = 0; i < n; i++) {
+ double x, y;
+ PyObject *op = PyTuple_GET_ITEM(data, i);
+ if (PyFloat_Check(op))
+ xy[j++] = PyFloat_AS_DOUBLE(op);
+ else if (PyInt_Check(op))
+ xy[j++] = (float) PyInt_AS_LONG(op);
+ else if (PyNumber_Check(op))
+ xy[j++] = PyFloat_AsDouble(op);
+ else if (PyArg_ParseTuple(op, "dd", &x, &y)) {
+ xy[j++] = x;
+ xy[j++] = y;
+ } else {
+ free(xy);
+ return -1;
+ }
+ }
+ } else {
+ for (i = 0; i < n; i++) {
+ double x, y;
+ PyObject *op = PySequence_GetItem(data, i);
+ if (!op) {
+ /* treat IndexError as end of sequence */
+ if (PyErr_Occurred() &&
+ PyErr_ExceptionMatches(PyExc_IndexError)) {
+ PyErr_Clear();
+ break;
+ } else {
+ free(xy);
+ return -1;
+ }
+ }
+ if (PyFloat_Check(op))
+ xy[j++] = PyFloat_AS_DOUBLE(op);
+ else if (PyInt_Check(op))
+ xy[j++] = (float) PyInt_AS_LONG(op);
+ else if (PyNumber_Check(op))
+ xy[j++] = PyFloat_AsDouble(op);
+ else if (PyArg_ParseTuple(op, "dd", &x, &y)) {
+ xy[j++] = x;
+ xy[j++] = y;
+ } else {
+ Py_DECREF(op);
+ free(xy);
+ return -1;
+ }
+ Py_DECREF(op);
+ }
+ }
+
+ if (j & 1) {
+ PyErr_SetString(PyExc_ValueError, "wrong number of coordinates");
+ free(xy);
+ return -1;
+ }
+
+ *pxy = xy;
+ return j/2;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Factories */
+/* -------------------------------------------------------------------- */
+
+PyObject*
+PyPath_Create(PyObject* self, PyObject* args)
+{
+ PyObject* data;
+ int count;
+ double *xy;
+
+ if (PyArg_ParseTuple(args, "i:Path", &count)) {
+
+ /* number of vertices */
+ xy = alloc_array(count);
+ if (!xy)
+ return NULL;
+
+ } else {
+
+ /* sequence or other path */
+ PyErr_Clear();
+ if (!PyArg_ParseTuple(args, "O", &data))
+ return NULL;
+
+ count = PyPath_Flatten(data, &xy);
+ if (count < 0)
+ return NULL;
+ }
+
+ return (PyObject*) path_new(count, xy, 0);
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Methods */
+/* -------------------------------------------------------------------- */
+
+static PyObject*
+path_compact(PyPathObject* self, PyObject* args)
+{
+ /* Simple-minded method to shorten path. A point is removed if
+ the city block distance to the previous point is less than the
+ given distance */
+ int i, j;
+ double *xy;
+
+ double cityblock = 2.0;
+
+ if (!PyArg_ParseTuple(args, "|d:compact", &cityblock))
+ return NULL;
+
+ xy = self->xy;
+
+ /* remove bogus vertices */
+ for (i = j = 1; i < self->count; i++) {
+ if (fabs(xy[j+j-2]-xy[i+i]) + fabs(xy[j+j-1]-xy[i+i+1]) >= cityblock) {
+ xy[j+j] = xy[i+i];
+ xy[j+j+1] = xy[i+i+1];
+ j++;
+ }
+ }
+
+ i = self->count - j;
+ self->count = j;
+
+ /* shrink coordinate array */
+ self->xy = realloc(self->xy, 2 * self->count * sizeof(double));
+
+ return Py_BuildValue("i", i); /* number of removed vertices */
+}
+
+static PyObject*
+path_clip_polygon(PyPathObject* self, PyObject* args)
+{
+ /* Clip path representing a single polygon */
+ PyErr_SetString(PyExc_RuntimeError, "not yet implemented");
+ return NULL;
+}
+
+static PyObject*
+path_clip_polyline(PyPathObject* self, PyObject* args)
+{
+ /* Clip path representing a single polyline (outline) */
+ PyErr_SetString(PyExc_RuntimeError, "not yet implemented");
+ return NULL;
+}
+
+static PyObject*
+path_getbbox(PyPathObject* self, PyObject* args)
+{
+ /* Find bounding box */
+ int i;
+ double *xy;
+ double x0, y0, x1, y1;
+
+ if (!PyArg_ParseTuple(args, ":getbbox"))
+ return NULL;
+
+ xy = self->xy;
+
+ x0 = x1 = xy[0];
+ y0 = y1 = xy[1];
+
+ for (i = 1; i < self->count; i++) {
+ if (xy[i+i] < x0)
+ x0 = xy[i+i];
+ if (xy[i+i] > x1)
+ x1 = xy[i+i];
+ if (xy[i+i+1] < y0)
+ y0 = xy[i+i+1];
+ if (xy[i+i+1] > y1)
+ y1 = xy[i+i+1];
+ }
+
+ return Py_BuildValue("dddd", x0, y0, x1, y1);
+}
+
+static PyObject*
+path_getitem(PyPathObject* self, int i)
+{
+ if (i < 0 || i >= self->count) {
+ PyErr_SetString(PyExc_IndexError, "path index out of range");
+ return NULL;
+ }
+
+ return Py_BuildValue("dd", self->xy[i+i], self->xy[i+i+1]);
+}
+
+static PyObject*
+path_getslice(PyPathObject* self, int ilow, int ihigh)
+{
+ /* adjust arguments */
+ if (ilow < 0)
+ ilow = 0;
+ else if (ilow >= self->count)
+ ilow = self->count;
+ if (ihigh < 0)
+ ihigh = 0;
+ if (ihigh < ilow)
+ ihigh = ilow;
+ else if (ihigh > self->count)
+ ihigh = self->count;
+
+ return (PyObject*) path_new(ihigh - ilow, self->xy + ilow * 2, 1);
+}
+
+static int
+path_len(PyPathObject* self)
+{
+ return self->count;
+}
+
+static PyObject*
+path_map(PyPathObject* self, PyObject* args)
+{
+ /* Map coordinate set through function */
+ int i;
+ double *xy;
+ PyObject* function;
+
+ if (!PyArg_ParseTuple(args, "O:map", &function))
+ return NULL;
+
+ xy = self->xy;
+
+ /* apply function to coordinate set */
+ for (i = 0; i < self->count; i++) {
+ double x = xy[i+i];
+ double y = xy[i+i+1];
+ PyObject* item = PyObject_CallFunction(function, "dd", x, y);
+ if (!item || !PyArg_ParseTuple(item, "dd", &x, &y)) {
+ Py_XDECREF(item);
+ return NULL;
+ }
+ xy[i+i] = x;
+ xy[i+i+1] = y;
+ Py_DECREF(item);
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static int
+path_setitem(PyPathObject* self, int i, PyObject* op)
+{
+ double* xy;
+
+ if (i < 0 || i >= self->count) {
+ PyErr_SetString(PyExc_IndexError,
+ "path assignment index out of range");
+ return -1;
+ }
+
+ if (op == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "cannot delete from path");
+ return -1;
+ }
+
+ xy = &self->xy[i+i];
+
+ if (!PyArg_ParseTuple(op, "dd", &xy[0], &xy[1]))
+ return -1;
+
+ return 0;
+}
+
+static PyObject*
+path_tolist(PyPathObject* self, PyObject* args)
+{
+ PyObject *list;
+ int i;
+
+ int flat = 0;
+ if (!PyArg_ParseTuple(args, "|i:tolist", &flat))
+ return NULL;
+
+ if (flat) {
+ list = PyList_New(self->count*2);
+ for (i = 0; i < self->count*2; i++) {
+ PyObject* item;
+ item = PyFloat_FromDouble(self->xy[i]);
+ if (!item)
+ goto error;
+ PyList_SetItem(list, i, item);
+ }
+ } else {
+ list = PyList_New(self->count);
+ for (i = 0; i < self->count; i++) {
+ PyObject* item;
+ item = Py_BuildValue("dd", self->xy[i+i], self->xy[i+i+1]);
+ if (!item)
+ goto error;
+ PyList_SetItem(list, i, item);
+ }
+ }
+
+ return list;
+
+error:
+ Py_DECREF(list);
+ return NULL;
+}
+
+static PyObject*
+path_transform(PyPathObject* self, PyObject* args)
+{
+ /* Apply affine transform to coordinate set */
+ int i;
+ double *xy;
+ double a, b, c, d, e, f;
+
+ double wrap = 0.0;
+
+ if (!PyArg_ParseTuple(args, "(dddddd)|d:transform",
+ &a, &b, &c, &d, &e, &f,
+ &wrap))
+ return NULL;
+
+ xy = self->xy;
+
+ /* transform the coordinate set */
+ if (b == 0.0 && d == 0.0)
+ /* scaling */
+ for (i = 0; i < self->count; i++) {
+ xy[i+i] = a*xy[i+i]+c;
+ xy[i+i+1] = e*xy[i+i+1]+f;
+ }
+ else
+ /* affine transform */
+ for (i = 0; i < self->count; i++) {
+ double x = xy[i+i];
+ double y = xy[i+i+1];
+ xy[i+i] = a*x+b*y+c;
+ xy[i+i+1] = d*x+e*y+f;
+ }
+
+ /* special treatment of geographical map data */
+ if (wrap != 0.0)
+ for (i = 0; i < self->count; i++)
+ xy[i+i] = fmod(xy[i+i], wrap);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static struct PyMethodDef methods[] = {
+ {"getbbox", (PyCFunction)path_getbbox, 1},
+ {"tolist", (PyCFunction)path_tolist, 1},
+ {"clip_polygon", (PyCFunction)path_clip_polygon, 1},
+ {"clip_polyline", (PyCFunction)path_clip_polyline, 1},
+ {"compact", (PyCFunction)path_compact, 1},
+ {"map", (PyCFunction)path_map, 1},
+ {"transform", (PyCFunction)path_transform, 1},
+ {NULL, NULL} /* sentinel */
+};
+
+static PyObject*
+path_getattr(PyPathObject* self, char* name)
+{
+ PyObject* res;
+
+ res = Py_FindMethod(methods, (PyObject*) self, name);
+ if (res)
+ return res;
+
+ PyErr_Clear();
+
+ if (strcmp(name, "id") == 0)
+ return Py_BuildValue("l", (long) self->xy);
+
+ PyErr_SetString(PyExc_AttributeError, name);
+ return NULL;
+}
+
+static PySequenceMethods path_as_sequence = {
+ (inquiry)path_len, /*sq_length*/
+ (binaryfunc)0, /*sq_concat*/
+ (ssizeargfunc)0, /*sq_repeat*/
+ (ssizeargfunc)path_getitem, /*sq_item*/
+ (ssizessizeargfunc)path_getslice, /*sq_slice*/
+ (ssizeobjargproc)path_setitem, /*sq_ass_item*/
+ (ssizessizeobjargproc)0, /*sq_ass_slice*/
+};
+
+statichere PyTypeObject PyPathType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "Path", /*tp_name*/
+ sizeof(PyPathObject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor)path_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ (getattrfunc)path_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number */
+ &path_as_sequence, /*tp_as_sequence */
+ 0, /*tp_as_mapping */
+ 0, /*tp_hash*/
+};
diff --git a/Imaging/selftest.py b/Imaging/selftest.py
new file mode 100644
index 0000000..6242ba5
--- /dev/null
+++ b/Imaging/selftest.py
@@ -0,0 +1,161 @@
+# $Id: selftest.py 2813 2006-10-07 10:11:35Z fredrik $
+# minimal sanity check
+
+import sys
+sys.path.insert(0, ".")
+sys.path.insert(1, "PIL")
+
+import Image
+import ImageDraw
+import ImageFilter
+import ImageMath
+
+try:
+ Image.core.ping
+except ImportError, v:
+ print "***", v
+ sys.exit()
+except AttributeError:
+ pass
+
+def _info(im):
+ im.load()
+ return im.format, im.mode, im.size
+
+def testimage():
+ """
+ PIL lets you create in-memory images with various pixel types:
+
+ >>> im = Image.new("1", (128, 128)) # monochrome
+ >>> _info(im)
+ (None, '1', (128, 128))
+ >>> _info(Image.new("L", (128, 128))) # grayscale (luminance)
+ (None, 'L', (128, 128))
+ >>> _info(Image.new("P", (128, 128))) # palette
+ (None, 'P', (128, 128))
+ >>> _info(Image.new("RGB", (128, 128))) # truecolor
+ (None, 'RGB', (128, 128))
+ >>> _info(Image.new("I", (128, 128))) # 32-bit integer
+ (None, 'I', (128, 128))
+ >>> _info(Image.new("F", (128, 128))) # 32-bit floating point
+ (None, 'F', (128, 128))
+
+ Or open existing files:
+
+ >>> im = Image.open("Images/lena.gif")
+ >>> _info(im)
+ ('GIF', 'P', (128, 128))
+ >>> _info(Image.open("Images/lena.ppm"))
+ ('PPM', 'RGB', (128, 128))
+ >>> _info(Image.open("Images/lena.jpg"))
+ ('JPEG', 'RGB', (128, 128))
+
+ PIL doesn't actually load the image data until it's needed,
+ or you call the "load" method:
+
+ >>> im = Image.open("Images/lena.ppm")
+ >>> print im.im # internal image attribute
+ None
+ >>> a = im.load()
+ >>> type(im.im)
+ <type 'ImagingCore'>
+
+ You can apply many different operations on images. Most
+ operations return a new image:
+
+ >>> im = Image.open("Images/lena.ppm")
+ >>> _info(im.convert("L"))
+ (None, 'L', (128, 128))
+ >>> _info(im.copy())
+ (None, 'RGB', (128, 128))
+ >>> _info(im.crop((32, 32, 96, 96)))
+ (None, 'RGB', (64, 64))
+ >>> _info(im.filter(ImageFilter.BLUR))
+ (None, 'RGB', (128, 128))
+ >>> im.getbands()
+ ('R', 'G', 'B')
+ >>> im.getbbox()
+ (0, 0, 128, 128)
+ >>> len(im.getdata())
+ 16384
+ >>> im.getextrema()
+ ((61, 255), (26, 234), (44, 223))
+ >>> im.getpixel((0, 0))
+ (223, 162, 133)
+ >>> len(im.getprojection())
+ 2
+ >>> len(im.histogram())
+ 768
+ >>> _info(im.point(range(256)*3))
+ (None, 'RGB', (128, 128))
+ >>> _info(im.resize((64, 64)))
+ (None, 'RGB', (64, 64))
+ >>> _info(im.rotate(45))
+ (None, 'RGB', (128, 128))
+ >>> map(_info, im.split())
+ [(None, 'L', (128, 128)), (None, 'L', (128, 128)), (None, 'L', (128, 128))]
+ >>> len(im.convert("1").tobitmap())
+ 10456
+ >>> len(im.tostring())
+ 49152
+ >>> _info(im.transform((512, 512), Image.AFFINE, (1,0,0,0,1,0)))
+ (None, 'RGB', (512, 512))
+ >>> _info(im.transform((512, 512), Image.EXTENT, (32,32,96,96)))
+ (None, 'RGB', (512, 512))
+
+ The ImageDraw module lets you draw stuff in raster images:
+
+ >>> im = Image.new("L", (128, 128), 64)
+ >>> d = ImageDraw.ImageDraw(im)
+ >>> d.line((0, 0, 128, 128), fill=128)
+ >>> d.line((0, 128, 128, 0), fill=128)
+ >>> im.getextrema()
+ (64, 128)
+
+ In 1.1.4, you can specify colors in a number of ways:
+
+ >>> xy = 0, 0, 128, 128
+ >>> im = Image.new("RGB", (128, 128), 0)
+ >>> d = ImageDraw.ImageDraw(im)
+ >>> d.rectangle(xy, "#f00")
+ >>> im.getpixel((0, 0))
+ (255, 0, 0)
+ >>> d.rectangle(xy, "#ff0000")
+ >>> im.getpixel((0, 0))
+ (255, 0, 0)
+ >>> d.rectangle(xy, "rgb(255,0,0)")
+ >>> im.getpixel((0, 0))
+ (255, 0, 0)
+ >>> d.rectangle(xy, "rgb(100%,0%,0%)")
+ >>> im.getpixel((0, 0))
+ (255, 0, 0)
+ >>> d.rectangle(xy, "hsl(0, 100%, 50%)")
+ >>> im.getpixel((0, 0))
+ (255, 0, 0)
+ >>> d.rectangle(xy, "red")
+ >>> im.getpixel((0, 0))
+ (255, 0, 0)
+
+ In 1.1.6, you can use the ImageMath module to do image
+ calculations.
+
+ >>> im = ImageMath.eval("float(im + 20)", im=im.convert("L"))
+ >>> im.mode, im.size
+ ('F', (128, 128))
+
+ PIL can do many other things, but I'll leave that for another
+ day. If you're curious, check the handbook, available from:
+
+ http://www.pythonware.com
+
+ Cheers /F
+ """
+
+if __name__ == "__main__":
+ # use doctest to make sure the test program behaves as documented!
+ import doctest, selftest
+ status = doctest.testmod(selftest)
+ if status[0]:
+ print "*** %s tests of %d failed." % status
+ else:
+ print "%s tests passed." % status[1]
diff --git a/Imaging/setup.py b/Imaging/setup.py
new file mode 100644
index 0000000..aee3d2d
--- /dev/null
+++ b/Imaging/setup.py
@@ -0,0 +1,457 @@
+#!/usr/bin/env python
+#
+# Setup script for PIL 1.1.5 and later
+# $Id: setup.py 2582 2005-11-11 21:54:00Z fredrik $
+#
+# Usage: python setup.py install
+#
+
+import glob, os, re, struct, string, sys
+
+# make it possible to run the setup script from another directory
+try:
+ os.chdir(os.path.dirname(sys.argv[0]))
+except OSError:
+ pass
+
+def libinclude(root):
+ # map root to (root/lib, root/include)
+ return os.path.join(root, "lib"), os.path.join(root, "include")
+
+# --------------------------------------------------------------------
+# Library pointers.
+#
+# Use None to look for the libraries in well-known library locations.
+# Use a string to specify a single directory, for both the library and
+# the include files. Use a tuple to specify separate directories:
+# (libpath, includepath). Examples:
+#
+# JPEG_ROOT = "/home/libraries/jpeg-6b"
+# TIFF_ROOT = "/opt/tiff/lib", "/opt/tiff/include"
+#
+# If you have "lib" and "include" directories under a common parent,
+# you can use the "libinclude" helper:
+#
+# TIFF_ROOT = libinclude("/opt/tiff")
+
+FREETYPE_ROOT = None
+JPEG_ROOT = None
+TIFF_ROOT = None
+ZLIB_ROOT = None
+TCL_ROOT = None
+
+# FIXME: add mechanism to explicitly *disable* the use of a library
+
+# --------------------------------------------------------------------
+# Identification
+
+NAME = "PIL"
+DESCRIPTION = "Python Imaging Library"
+AUTHOR = "Secret Labs AB (PythonWare)", "info@pythonware.com"
+HOMEPAGE = "http://www.pythonware.com/products/pil"
+
+# --------------------------------------------------------------------
+# Core library
+
+IMAGING = [
+ "decode", "encode", "map", "display", "outline", "path",
+ ]
+
+LIBIMAGING = [
+ "Access", "Antialias", "Bands", "BitDecode", "Blend", "Chops",
+ "Convert", "ConvertYCbCr", "Copy", "Crc32", "Crop", "Dib", "Draw",
+ "Effects", "EpsEncode", "File", "Fill", "Filter", "FliDecode",
+ "Geometry", "GetBBox", "GifDecode", "GifEncode", "HexDecode",
+ "Histo", "JpegDecode", "JpegEncode", "LzwDecode", "Matrix",
+ "ModeFilter", "MspDecode", "Negative", "Offset", "Pack",
+ "PackDecode", "Palette", "Paste", "Quant", "QuantHash",
+ "QuantHeap", "PcdDecode", "PcxDecode", "PcxEncode", "Point",
+ "RankFilter", "RawDecode", "RawEncode", "Storage", "SunRleDecode",
+ "TgaRleDecode", "Unpack", "UnpackYCC", "XbmDecode", "XbmEncode",
+ "ZipDecode", "ZipEncode"
+ ]
+
+# --------------------------------------------------------------------
+# Override settings
+
+try:
+ from setup_site import *
+except ImportError:
+ pass
+
+# --------------------------------------------------------------------
+
+from distutils import sysconfig
+from distutils.core import Extension, setup
+from distutils.command.build_ext import build_ext
+
+try:
+ import _tkinter
+except ImportError:
+ _tkinter = None
+
+def add_directory(path, dir, where=None):
+ if dir and os.path.isdir(dir) and dir not in path:
+ if where is None:
+ path.append(dir)
+ else:
+ path.insert(where, dir)
+
+def find_library_file(self, library):
+ return self.compiler.find_library_file(self.compiler.library_dirs, library)
+
+def find_version(filename):
+ for line in open(filename).readlines():
+ m = re.search("VERSION\s*=\s*\"([^\"]+)\"", line)
+ if m:
+ return m.group(1)
+ return None
+
+VERSION = find_version("PIL/Image.py")
+
+class pil_build_ext(build_ext):
+
+ def build_extensions(self):
+
+ global TCL_ROOT
+
+ library_dirs = []
+ include_dirs = []
+
+ add_directory(include_dirs, "libImaging")
+
+ #
+ # add platform directories
+
+ if sys.platform == "cygwin":
+ # pythonX.Y.dll.a is in the /usr/lib/pythonX.Y/config directory
+ add_directory(library_dirs, os.path.join(
+ "/usr/lib", "python%s" % sys.version[:3], "config"
+ ))
+
+ elif sys.platform == "darwin":
+ # attempt to make sure we pick freetype2 over other versions
+ add_directory(include_dirs, "/sw/include/freetype2")
+ add_directory(include_dirs, "/sw/lib/freetype2/include")
+ # fink installation directories
+ add_directory(library_dirs, "/sw/lib")
+ add_directory(include_dirs, "/sw/include")
+ # darwin ports installation directories
+ add_directory(library_dirs, "/opt/local/lib")
+ add_directory(include_dirs, "/opt/local/include")
+
+ add_directory(library_dirs, "/usr/local/lib")
+ # FIXME: check /opt/stuff directories here?
+
+ prefix = sysconfig.get_config_var("prefix")
+ if prefix:
+ add_directory(library_dirs, os.path.join(prefix, "lib"))
+ add_directory(include_dirs, os.path.join(prefix, "include"))
+
+ #
+ # locate tkinter libraries
+
+ if _tkinter:
+ TCL_VERSION = _tkinter.TCL_VERSION[:3]
+
+ if _tkinter and not TCL_ROOT:
+ # we have Tkinter but the TCL_ROOT variable was not set;
+ # try to locate appropriate Tcl/Tk libraries
+ PYVERSION = sys.version[0] + sys.version[2]
+ TCLVERSION = TCL_VERSION[0] + TCL_VERSION[2]
+ roots = [
+ # common installation directories, mostly for Windows
+ # (for Unix-style platforms, we'll check in well-known
+ # locations later)
+ os.path.join("/py" + PYVERSION, "Tcl"),
+ os.path.join("/python" + PYVERSION, "Tcl"),
+ "/Tcl", "/Tcl" + TCLVERSION, "/Tcl" + TCL_VERSION,
+ os.path.join(os.environ.get("ProgramFiles", ""), "Tcl"),
+ ]
+ for TCL_ROOT in roots:
+ TCL_ROOT = os.path.abspath(TCL_ROOT)
+ if os.path.isfile(os.path.join(TCL_ROOT, "include", "tk.h")):
+ # FIXME: use distutils logging (?)
+ print "--- using Tcl/Tk libraries at", TCL_ROOT
+ print "--- using Tcl/Tk version", TCL_VERSION
+ TCL_ROOT = libinclude(TCL_ROOT)
+ break
+ else:
+ TCL_ROOT = None
+
+ #
+ # add configured kits
+
+ for root in [FREETYPE_ROOT, JPEG_ROOT, TCL_ROOT, TIFF_ROOT, ZLIB_ROOT]:
+ if isinstance(root, type(())):
+ lib_root, include_root = root
+ else:
+ lib_root = include_root = root
+ add_directory(library_dirs, lib_root)
+ add_directory(include_dirs, include_root)
+
+ #
+ # add standard directories
+
+ add_directory(library_dirs, "/usr/local/lib")
+ add_directory(include_dirs, "/usr/local/include")
+
+ add_directory(library_dirs, "/usr/lib")
+ add_directory(include_dirs, "/usr/include")
+
+ #
+ # insert new dirs *before* default libs, to avoid conflicts
+ # between Python PYD stub libs and real libraries
+
+ self.compiler.library_dirs = library_dirs + self.compiler.library_dirs
+ self.compiler.include_dirs = include_dirs + self.compiler.include_dirs
+
+ #
+ # look for available libraries
+
+ class feature:
+ zlib = jpeg = tiff = freetype = tcl = tk = None
+ feature = feature()
+
+ if find_library_file(self, "z"):
+ feature.zlib = "z"
+ elif sys.platform == "win32" and find_library_file(self, "zlib"):
+ feature.zlib = "zlib" # alternative name
+
+ if find_library_file(self, "jpeg"):
+ feature.jpeg = "jpeg"
+ elif sys.platform == "win32" and find_library_file(self, "libjpeg"):
+ feature.jpeg = "libjpeg" # alternative name
+
+ if find_library_file(self, "tiff"):
+ feature.tiff = "tiff"
+
+ if find_library_file(self, "freetype"):
+ # look for freetype2 include files
+ freetype_version = 0
+ for dir in self.compiler.include_dirs:
+ if os.path.isfile(os.path.join(dir, "ft2build.h")):
+ freetype_version = 21
+ dir = os.path.join(dir, "freetype2")
+ break
+ dir = os.path.join(dir, "freetype2")
+ if os.path.isfile(os.path.join(dir, "ft2build.h")):
+ freetype_version = 21
+ break
+ if os.path.isdir(os.path.join(dir, "freetype")):
+ freetype_version = 20
+ break
+ if freetype_version:
+ feature.freetype = "freetype"
+ feature.freetype_version = freetype_version
+ if dir:
+ add_directory(self.compiler.include_dirs, dir, 0)
+
+ if _tkinter:
+ # the library names may vary somewhat (e.g. tcl84 or tcl8.4)
+ version = TCL_VERSION[0] + TCL_VERSION[2]
+ if find_library_file(self, "tcl" + version):
+ feature.tcl = "tcl" + version
+ elif find_library_file(self, "tcl" + TCL_VERSION):
+ feature.tcl = "tcl" + TCL_VERSION
+ if find_library_file(self, "tk" + version):
+ feature.tk = "tk" + version
+ elif find_library_file(self, "tk" + TCL_VERSION):
+ feature.tk = "tk" + TCL_VERSION
+
+ #
+ # core library
+
+ files = ["_imaging.c"]
+ for file in IMAGING:
+ files.append(file + ".c")
+ for file in LIBIMAGING:
+ files.append(os.path.join("libImaging", file + ".c"))
+
+ libs = []
+ defs = []
+ if feature.jpeg:
+ libs.append(feature.jpeg)
+ defs.append(("HAVE_LIBJPEG", None))
+ if feature.zlib:
+ libs.append(feature.zlib)
+ defs.append(("HAVE_LIBZ", None))
+ if sys.platform == "win32":
+ libs.extend(["kernel32", "user32", "gdi32"])
+ if struct.unpack("h", "\0\1")[0] == 1:
+ defs.append(("WORDS_BIGENDIAN", None))
+
+ exts = [(Extension(
+ "_imaging", files, libraries=libs, define_macros=defs
+ ))]
+
+ #
+ # additional libraries
+
+ if feature.freetype:
+ defs = []
+ if feature.freetype_version == 20:
+ defs.append(("USE_FREETYPE_2_0", None))
+ exts.append(Extension(
+ "_imagingft", ["_imagingft.c"], libraries=["freetype"],
+ define_macros=defs
+ ))
+
+ if os.path.isfile("_imagingtiff.c") and feature.tiff:
+ exts.append(Extension(
+ "_imagingtiff", ["_imagingtiff.c"], libraries=["tiff"]
+ ))
+
+ if sys.platform == "darwin":
+ # locate Tcl/Tk frameworks
+ frameworks = []
+ framework_roots = [
+ "/Library/Frameworks",
+ "/System/Library/Frameworks"
+ ]
+ for root in framework_roots:
+ if (os.path.exists(os.path.join(root, "Tcl.framework")) and
+ os.path.exists(os.path.join(root, "Tk.framework"))):
+ print "--- using frameworks at", root
+ frameworks = ["-framework", "Tcl", "-framework", "Tk"]
+ dir = os.path.join(root, "Tcl.framework", "Headers")
+ add_directory(self.compiler.include_dirs, dir, 0)
+ dir = os.path.join(root, "Tk.framework", "Headers")
+ add_directory(self.compiler.include_dirs, dir, 1)
+ break
+ if frameworks:
+ exts.append(Extension(
+ "_imagingtk", ["_imagingtk.c", "Tk/tkImaging.c"],
+ extra_compile_args=frameworks, extra_link_args=frameworks
+ ))
+ feature.tcl = feature.tk = 1 # mark as present
+ elif feature.tcl and feature.tk:
+ exts.append(Extension(
+ "_imagingtk", ["_imagingtk.c", "Tk/tkImaging.c"],
+ libraries=[feature.tcl, feature.tk]
+ ))
+
+ if os.path.isfile("_imagingmath.c"):
+ exts.append(Extension("_imagingmath", ["_imagingmath.c"]))
+
+ self.extensions[:] = exts
+
+ build_ext.build_extensions(self)
+
+ #
+ # sanity and security checks
+
+ unsafe_zlib = None
+
+ if feature.zlib:
+ unsafe_zlib = self.check_zlib_version(self.compiler.include_dirs)
+
+ self.summary_report(feature, unsafe_zlib)
+
+ def summary_report(self, feature, unsafe_zlib):
+
+ print "-" * 68
+ print "PIL", VERSION, "BUILD SUMMARY"
+ print "-" * 68
+ print "version ", VERSION
+ v = string.split(sys.version, "[")
+ print "platform ", sys.platform, string.strip(v[0])
+ for v in v[1:]:
+ print " ", string.strip("[" + v)
+ print "-" * 68
+
+ options = [
+ (feature.tcl and feature.tk, "TKINTER"),
+ (feature.jpeg, "JPEG"),
+ (feature.zlib, "ZLIB (PNG/ZIP)"),
+ # (feature.tiff, "experimental TIFF G3/G4 read"),
+ (feature.freetype, "FREETYPE2"),
+ ]
+
+ all = 1
+ for option in options:
+ if option[0]:
+ print "---", option[1], "support ok"
+ else:
+ print "***", option[1], "support not available",
+ if option[1] == "TKINTER" and _tkinter:
+ version = _tkinter.TCL_VERSION
+ print "(Tcl/Tk %s libraries needed)" % version,
+ print
+ all = 0
+
+ if feature.zlib and unsafe_zlib:
+ print
+ print "*** Warning: zlib", unsafe_zlib,
+ print "may contain a security vulnerability."
+ print "*** Consider upgrading to zlib 1.2.3 or newer."
+ print "*** See: http://www.kb.cert.org/vuls/id/238678"
+ print " http://www.kb.cert.org/vuls/id/680620"
+ print " http://www.gzip.org/zlib/advisory-2002-03-11.txt"
+ print
+
+ print "-" * 68
+
+ if not all:
+ print "To add a missing option, make sure you have the required"
+ print "library, and set the corresponding ROOT variable in the"
+ print "setup.py script."
+ print
+
+ print "To check the build, run the selftest.py script."
+
+ def check_zlib_version(self, include_dirs):
+ # look for unsafe versions of zlib
+ for dir in include_dirs:
+ zlibfile = os.path.join(dir, "zlib.h")
+ if os.path.isfile(zlibfile):
+ break
+ else:
+ return
+ for line in open(zlibfile).readlines():
+ m = re.match('#define\s+ZLIB_VERSION\s+"([^"]*)"', line)
+ if not m:
+ continue
+ if m.group(1) < "1.2.3":
+ return m.group(1)
+
+#
+# build!
+
+if __name__ == "__main__":
+
+ try:
+ # add necessary to distutils (for backwards compatibility)
+ from distutils.dist import DistributionMetadata
+ DistributionMetadata.classifiers = None
+ DistributionMetadata.download_url = None
+ DistributionMetadata.platforms = None
+ except:
+ pass
+
+ setup(
+ author=AUTHOR[0], author_email=AUTHOR[1],
+ classifiers=[
+ "Development Status :: 6 - Mature",
+ "Topic :: Multimedia :: Graphics",
+ "Topic :: Multimedia :: Graphics :: Capture :: Digital Camera",
+ "Topic :: Multimedia :: Graphics :: Capture :: Scanners",
+ "Topic :: Multimedia :: Graphics :: Capture :: Screen Capture",
+ "Topic :: Multimedia :: Graphics :: Graphics Conversion",
+ "Topic :: Multimedia :: Graphics :: Viewers",
+ ],
+ cmdclass = {"build_ext": pil_build_ext},
+ description=DESCRIPTION,
+ download_url="http://effbot.org/zone/pil-changes-116.htm",
+ ext_modules = [Extension("_imaging", ["_imaging.c"])], # dummy
+ extra_path = "PIL",
+ license="Python (MIT style)",
+ long_description=DESCRIPTION,
+ name=NAME,
+ package_dir={"": "PIL"},
+ packages=[""],
+ platforms="Python 1.5.2 and later.",
+ scripts = glob.glob("Scripts/pil*.py"),
+ url=HOMEPAGE,
+ version=VERSION,
+ )
diff --git a/MANIFEST b/MANIFEST
index 5d698c0..6683640 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1,116 +1,396 @@
-ImageProcessor.activity/
-ImageProcessor.activity/activity
-ImageProcessor.activity/activity/activity-imageprocessor.svg
-ImageProcessor.activity/activity/activity.info
-ImageProcessor.activity/icons
-ImageProcessor.activity/icons/blur.svg
-ImageProcessor.activity/icons/cam.svg
-ImageProcessor.activity/icons/contour.svg
-ImageProcessor.activity/icons/copy.svg
-ImageProcessor.activity/icons/embross.svg
-ImageProcessor.activity/icons/finedges.svg
-ImageProcessor.activity/icons/grey.svg
-ImageProcessor.activity/icons/invert.svg
-ImageProcessor.activity/icons/left_bottom.svg
-ImageProcessor.activity/icons/left_top.svg
-ImageProcessor.activity/icons/mirror.svg
-ImageProcessor.activity/icons/offset.svg
-ImageProcessor.activity/icons/original.svg
-ImageProcessor.activity/icons/paste.svg
-ImageProcessor.activity/icons/right_bottom.svg
-ImageProcessor.activity/icons/right_top.svg
-ImageProcessor.activity/icons/rotate_anticlockwise.svg
-ImageProcessor.activity/icons/rotate_clockwise.svg
-ImageProcessor.activity/icons/sharpen.svg
-ImageProcessor.activity/icons/solarize.svg
-ImageProcessor.activity/icons/watermark_scale.svg
-ImageProcessor.activity/icons/watermark_tile.svg
-ImageProcessor.activity/icons/watermark_tl.svg
-ImageProcessor.activity/ImageProcess.py
-ImageProcessor.activity/ImageProcess.py~
-ImageProcessor.activity/ImageProcessor.xo
-ImageProcessor.activity/ImageProcessorActivity.py
-ImageProcessor.activity/MANIFEST
-ImageProcessor.activity/pic.py
-ImageProcessor.activity/PIL
-ImageProcessor.activity/PIL/ImageGL.py
-ImageProcessor.activity/PIL/PixarImagePlugin.py
-ImageProcessor.activity/PIL/ArgImagePlugin.py
-ImageProcessor.activity/PIL/BdfFontFile.py
-ImageProcessor.activity/PIL/BmpImagePlugin.py
-ImageProcessor.activity/PIL/BufrStubImagePlugin.py
-ImageProcessor.activity/PIL/ContainerIO.py
-ImageProcessor.activity/PIL/CurImagePlugin.py
-ImageProcessor.activity/PIL/DcxImagePlugin.py
-ImageProcessor.activity/PIL/EpsImagePlugin.py
-ImageProcessor.activity/PIL/ExifTags.py
-ImageProcessor.activity/PIL/FitsStubImagePlugin.py
-ImageProcessor.activity/PIL/FliImagePlugin.py
-ImageProcessor.activity/PIL/FontFile.py
-ImageProcessor.activity/PIL/FpxImagePlugin.py
-ImageProcessor.activity/PIL/GbrImagePlugin.py
-ImageProcessor.activity/PIL/GdImageFile.py
-ImageProcessor.activity/PIL/GifImagePlugin.py
-ImageProcessor.activity/PIL/GimpGradientFile.py
-ImageProcessor.activity/PIL/GimpPaletteFile.py
-ImageProcessor.activity/PIL/GribStubImagePlugin.py
-ImageProcessor.activity/PIL/Hdf5StubImagePlugin.py
-ImageProcessor.activity/PIL/IcnsImagePlugin.py
-ImageProcessor.activity/PIL/IcoImagePlugin.py
-ImageProcessor.activity/PIL/Image.py
-ImageProcessor.activity/PIL/ImageChops.py
-ImageProcessor.activity/PIL/ImageColor.py
-ImageProcessor.activity/PIL/ImageDraw.py
-ImageProcessor.activity/PIL/ImageDraw2.py
-ImageProcessor.activity/PIL/ImageEnhance.py
-ImageProcessor.activity/PIL/ImageFile.py
-ImageProcessor.activity/PIL/ImageFileIO.py
-ImageProcessor.activity/PIL/ImageFilter.py
-ImageProcessor.activity/PIL/ImageFont.py
-ImageProcessor.activity/PIL/PngImagePlugin.py
-ImageProcessor.activity/PIL/PpmImagePlugin.py
-ImageProcessor.activity/PIL/PsdImagePlugin.py
-ImageProcessor.activity/PIL/PSDraw.py
-ImageProcessor.activity/PIL/SgiImagePlugin.py
-ImageProcessor.activity/PIL/SpiderImagePlugin.py
-ImageProcessor.activity/PIL/SunImagePlugin.py
-ImageProcessor.activity/PIL/TarIO.py
-ImageProcessor.activity/PIL/TgaImagePlugin.py
-ImageProcessor.activity/PIL/TiffImagePlugin.py
-ImageProcessor.activity/PIL/TiffTags.py
-ImageProcessor.activity/PIL/WalImageFile.py
-ImageProcessor.activity/PIL/WmfImagePlugin.py
-ImageProcessor.activity/PIL/XbmImagePlugin.py
-ImageProcessor.activity/PIL/XpmImagePlugin.py
-ImageProcessor.activity/PIL/XVThumbImagePlugin.py
-ImageProcessor.activity/PIL/__init__.py
-ImageProcessor.activity/PIL/ImageGrab.py
-ImageProcessor.activity/PIL/ImageMath.py
-ImageProcessor.activity/PIL/ImageMode.py
-ImageProcessor.activity/PIL/ImageOps.py
-ImageProcessor.activity/PIL/ImagePalette.py
-ImageProcessor.activity/PIL/ImagePath.py
-ImageProcessor.activity/PIL/ImageQt.py
-ImageProcessor.activity/PIL/ImageSequence.py
-ImageProcessor.activity/PIL/ImageStat.py
-ImageProcessor.activity/PIL/ImageTk.py
-ImageProcessor.activity/PIL/ImageTransform.py
-ImageProcessor.activity/PIL/ImageWin.py
-ImageProcessor.activity/PIL/ImImagePlugin.py
-ImageProcessor.activity/PIL/ImtImagePlugin.py
-ImageProcessor.activity/PIL/IptcImagePlugin.py
-ImageProcessor.activity/PIL/JpegImagePlugin.py
-ImageProcessor.activity/PIL/McIdasImagePlugin.py
-ImageProcessor.activity/PIL/MicImagePlugin.py
-ImageProcessor.activity/PIL/MpegImagePlugin.py
-ImageProcessor.activity/PIL/MspImagePlugin.py
-ImageProcessor.activity/PIL/OleFileIO.py
-ImageProcessor.activity/PIL/PaletteFile.py
-ImageProcessor.activity/PIL/PalmImagePlugin.py
-ImageProcessor.activity/PIL/PcdImagePlugin.py
-ImageProcessor.activity/PIL/PcfFontFile.py
-ImageProcessor.activity/PIL/PcxImagePlugin.py
-ImageProcessor.activity/PIL/PdfImagePlugin.py
-ImageProcessor.activity/ProgressDialog.py
-ImageProcessor.activity/setup.py
-ImageProcessor.activity/toolbar.py
+COPYING
+HACKING
+ImageProcess.py
+ImageProcessorActivity.py
+ProgressDialog.py
+setup.py
+toolbar.py
+activity/activity-imageprocessor.svg
+activity/activity.info
+
+
+
+
+icons/embross.svg
+
+icons/grey.svg
+icons/invert.svg
+icons/left_bottom.svg
+
+icons/mirror.svg
+
+icons/original.svg
+
+icons/right_bottom.svg
+icons/right_top.svg
+icons/rotate_anticlockwise.svg
+icons/rotate_clockwise.svg
+icons/sharpen.svg
+icons/solarize.svg
+icons/watermark_scale.svg
+icons/watermark_tile.svg
+icons/watermark_tl.svg
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+po/ImageProcessor.pot
+
+Imaging/BUILDME
+Imaging/CHANGES
+Imaging/CONTENTS
+Imaging/decode.c
+Imaging/display.c
+Imaging/doctest.py
+Imaging/encode.c
+Imaging/map.c
+Imaging/outline.c
+Imaging/path.c
+Imaging/PIL.pth
+Imaging/README
+Imaging/selftest.py
+Imaging/setup.py
+Imaging/_imaging.c
+Imaging/_imagingft.c
+Imaging/_imagingmath.c
+Imaging/_imagingtk.c
+Imaging/Docs/effbot.css
+Imaging/Docs/index.html
+Imaging/Docs/pythondoc-PIL.ContainerIO.html
+Imaging/Docs/pythondoc-PIL.CurImagePlugin.html
+Imaging/Docs/pythondoc-PIL.DcxImagePlugin.html
+Imaging/Docs/pythondoc-PIL.EpsImagePlugin.html
+Imaging/Docs/pythondoc-PIL.ExifTags.html
+Imaging/Docs/pythondoc-PIL.FitsStubImagePlugin.html
+Imaging/Docs/pythondoc-PIL.FliImagePlugin.html
+Imaging/Docs/pythondoc-PIL.FontFile.html
+Imaging/Docs/pythondoc-PIL.FpxImagePlugin.html
+Imaging/Docs/pythondoc-PIL.GbrImagePlugin.html
+Imaging/Docs/pythondoc-PIL.GdImageFile.html
+Imaging/Docs/pythondoc-PIL.GifImagePlugin.html
+Imaging/Docs/pythondoc-PIL.GimpGradientFile.html
+Imaging/Docs/pythondoc-PIL.GribStubImagePlugin.html
+Imaging/Docs/pythondoc-PIL.Hdf5StubImagePlugin.html
+Imaging/Docs/pythondoc-PIL.IcnsImagePlugin.html
+Imaging/Docs/pythondoc-PIL.IcoImagePlugin.html
+Imaging/Docs/pythondoc-PIL.Image.html
+Imaging/Docs/pythondoc-PIL.ImageChops.html
+Imaging/Docs/pythondoc-PIL.ImageColor.html
+Imaging/Docs/pythondoc-PIL.ImageDraw.html
+Imaging/Docs/pythondoc-PIL.ImageEnhance.html
+Imaging/Docs/pythondoc-PIL.ImageFile.html
+Imaging/Docs/pythondoc-PIL.ImageFileIO.html
+Imaging/Docs/pythondoc-PIL.ImageFilter.html
+Imaging/Docs/pythondoc-PIL.ImageFont.html
+Imaging/Docs/pythondoc-PIL.ArgImagePlugin.html
+Imaging/Docs/pythondoc-PIL.BdfFontFile.html
+Imaging/Docs/pythondoc-PIL.BmpImagePlugin.html
+Imaging/Docs/pythondoc-PIL.ImageGrab.html
+Imaging/Docs/pythondoc-PIL.ImageOps.html
+Imaging/Docs/pythondoc-PIL.ImagePalette.html
+Imaging/Docs/pythondoc-PIL.ImagePath.html
+Imaging/Docs/pythondoc-PIL.ImageSequence.html
+Imaging/Docs/pythondoc-PIL.ImageStat.html
+Imaging/Docs/pythondoc-PIL.ImageTk.html
+Imaging/Docs/pythondoc-PIL.ImageTransform.html
+Imaging/Docs/pythondoc-PIL.ImageWin.html
+Imaging/Docs/pythondoc-PIL.ImImagePlugin.html
+Imaging/Docs/pythondoc-PIL.ImtImagePlugin.html
+Imaging/Docs/pythondoc-PIL.IptcImagePlugin.html
+Imaging/Docs/pythondoc-PIL.JpegImagePlugin.html
+Imaging/Docs/pythondoc-PIL.BufrStubImagePlugin.html
+Imaging/Docs/pythondoc-PIL.GimpPaletteFile.html
+Imaging/Docs/pythondoc-PIL.ImageGL.html
+Imaging/Docs/pythondoc-PIL.McIdasImagePlugin.html
+Imaging/Docs/pythondoc-PIL.PsdImagePlugin.html
+Imaging/Docs/pythondoc-PIL.MicImagePlugin.html
+Imaging/Docs/pythondoc-PIL.MpegImagePlugin.html
+Imaging/Docs/pythondoc-PIL.MspImagePlugin.html
+Imaging/Docs/pythondoc-PIL.OleFileIO.html
+Imaging/Docs/pythondoc-PIL.PaletteFile.html
+Imaging/Docs/pythondoc-PIL.PalmImagePlugin.html
+Imaging/Docs/pythondoc-PIL.PcdImagePlugin.html
+Imaging/Docs/pythondoc-PIL.PcfFontFile.html
+Imaging/Docs/pythondoc-PIL.PcxImagePlugin.html
+Imaging/Docs/pythondoc-PIL.PdfImagePlugin.html
+Imaging/Docs/pythondoc-PIL.PixarImagePlugin.html
+Imaging/Docs/pythondoc-PIL.PngImagePlugin.html
+Imaging/Docs/pythondoc-PIL.PpmImagePlugin.html
+Imaging/Docs/pythondoc-PIL.PSDraw.html
+Imaging/Docs/pythondoc-PIL.SgiImagePlugin.html
+Imaging/Docs/pythondoc-PIL.SpiderImagePlugin.html
+Imaging/Docs/pythondoc-PIL.SunImagePlugin.html
+Imaging/Docs/pythondoc-PIL.TarIO.html
+Imaging/Docs/pythondoc-PIL.TgaImagePlugin.html
+Imaging/Docs/pythondoc-PIL.TiffImagePlugin.html
+Imaging/Docs/pythondoc-PIL.TiffTags.html
+Imaging/Docs/pythondoc-PIL.WalImageFile.html
+Imaging/Docs/pythondoc-PIL.WmfImagePlugin.html
+Imaging/Docs/pythondoc-PIL.XbmImagePlugin.html
+Imaging/Docs/pythondoc-PIL.XpmImagePlugin.html
+Imaging/Docs/pythondoc-PIL.XVThumbImagePlugin.html
+Imaging/Images/courB08.bdf
+Imaging/Images/courB08.pbm
+Imaging/Images/courB08.pil
+Imaging/Images/lena.gif
+Imaging/Images/lena.jpg
+Imaging/Images/lena.ppm
+Imaging/libImaging/Access.c
+Imaging/libImaging/Antialias.c
+Imaging/libImaging/Bands.c
+Imaging/libImaging/Bit.h
+Imaging/libImaging/BitDecode.c
+Imaging/libImaging/Blend.c
+Imaging/libImaging/Chops.c
+Imaging/libImaging/Convert.c
+Imaging/libImaging/ConvertYCbCr.c
+Imaging/libImaging/Copy.c
+Imaging/libImaging/Crc32.c
+Imaging/libImaging/Crop.c
+Imaging/libImaging/Dib.c
+Imaging/libImaging/Draw.c
+Imaging/libImaging/Effects.c
+Imaging/libImaging/EpsEncode.c
+Imaging/libImaging/Except.c
+Imaging/libImaging/File.c
+Imaging/libImaging/Fill.c
+Imaging/libImaging/Filter.c
+Imaging/libImaging/FliDecode.c
+Imaging/libImaging/Geometry.c
+Imaging/libImaging/GetBBox.c
+Imaging/libImaging/Gif.h
+Imaging/libImaging/GifDecode.c
+Imaging/libImaging/GifEncode.c
+Imaging/libImaging/HexDecode.c
+Imaging/libImaging/Histo.c
+Imaging/libImaging/Imaging.h
+Imaging/libImaging/ImDib.h
+Imaging/libImaging/ImPlatform.h
+Imaging/libImaging/Jpeg.h
+Imaging/libImaging/JpegDecode.c
+Imaging/libImaging/JpegEncode.c
+Imaging/libImaging/Lzw.h
+Imaging/libImaging/LzwDecode.c
+Imaging/libImaging/Matrix.c
+Imaging/libImaging/ModeFilter.c
+Imaging/libImaging/MspDecode.c
+Imaging/libImaging/Negative.c
+Imaging/libImaging/Offset.c
+Imaging/libImaging/Pack.c
+Imaging/libImaging/PackDecode.c
+Imaging/libImaging/Palette.c
+Imaging/libImaging/PcdDecode.c
+Imaging/libImaging/PcxDecode.c
+Imaging/libImaging/PcxEncode.c
+Imaging/libImaging/Point.c
+Imaging/libImaging/Quant.c
+Imaging/libImaging/Quant.h
+Imaging/libImaging/QuantDefines.h
+Imaging/libImaging/QuantHash.c
+Imaging/libImaging/QuantHash.h
+Imaging/libImaging/QuantHeap.c
+Imaging/libImaging/QuantHeap.h
+Imaging/libImaging/RankFilter.c
+Imaging/libImaging/Raw.h
+Imaging/libImaging/RawDecode.c
+Imaging/libImaging/RawEncode.c
+Imaging/libImaging/Storage.c
+Imaging/libImaging/SunRleDecode.c
+Imaging/libImaging/TgaRleDecode.c
+Imaging/libImaging/Unpack.c
+Imaging/libImaging/UnpackYCC.c
+Imaging/libImaging/XbmDecode.c
+Imaging/libImaging/XbmEncode.c
+Imaging/libImaging/Zip.h
+Imaging/libImaging/ZipDecode.c
+Imaging/libImaging/ZipEncode.c
+Imaging/libImaging/Paste.c
+Imaging/libImaging/QuantTypes.h
+Imaging/PIL/ArgImagePlugin.py
+Imaging/PIL/BdfFontFile.py
+Imaging/PIL/BmpImagePlugin.py
+Imaging/PIL/BufrStubImagePlugin.py
+Imaging/PIL/ContainerIO.py
+Imaging/PIL/CurImagePlugin.py
+Imaging/PIL/DcxImagePlugin.py
+Imaging/PIL/EpsImagePlugin.py
+Imaging/PIL/ExifTags.py
+Imaging/PIL/FliImagePlugin.py
+Imaging/PIL/FontFile.py
+Imaging/PIL/FpxImagePlugin.py
+Imaging/PIL/GbrImagePlugin.py
+Imaging/PIL/GdImageFile.py
+Imaging/PIL/GifImagePlugin.py
+Imaging/PIL/GimpGradientFile.py
+Imaging/PIL/GimpPaletteFile.py
+Imaging/PIL/GribStubImagePlugin.py
+Imaging/PIL/Hdf5StubImagePlugin.py
+Imaging/PIL/IcnsImagePlugin.py
+Imaging/PIL/IcoImagePlugin.py
+Imaging/PIL/Image.py
+Imaging/PIL/ImageChops.py
+Imaging/PIL/ImageColor.py
+Imaging/PIL/ImageDraw.py
+Imaging/PIL/ImageDraw2.py
+Imaging/PIL/ImageEnhance.py
+Imaging/PIL/ImageFile.py
+Imaging/PIL/ImageFilter.py
+Imaging/PIL/ImageFont.py
+Imaging/PIL/ImageGL.py
+Imaging/PIL/ImageGrab.py
+Imaging/PIL/ImageMath.py
+Imaging/PIL/ImageMode.py
+Imaging/PIL/ImageOps.py
+Imaging/PIL/ImagePalette.py
+Imaging/PIL/ImagePath.py
+Imaging/PIL/ImageSequence.py
+Imaging/PIL/ImageStat.py
+Imaging/PIL/ImageTk.py
+Imaging/PIL/ImageTransform.py
+Imaging/PIL/ImageWin.py
+Imaging/PIL/ImImagePlugin.py
+Imaging/PIL/ImtImagePlugin.py
+Imaging/PIL/IptcImagePlugin.py
+Imaging/PIL/JpegImagePlugin.py
+Imaging/PIL/McIdasImagePlugin.py
+Imaging/PIL/MicImagePlugin.py
+Imaging/PIL/MpegImagePlugin.py
+Imaging/PIL/MspImagePlugin.py
+Imaging/PIL/OleFileIO.py
+Imaging/PIL/PaletteFile.py
+Imaging/PIL/PalmImagePlugin.py
+Imaging/PIL/PcdImagePlugin.py
+Imaging/PIL/PcfFontFile.py
+Imaging/PIL/PcxImagePlugin.py
+Imaging/PIL/FitsStubImagePlugin.py
+Imaging/PIL/ImageFileIO.py
+Imaging/PIL/ImageQt.py
+Imaging/PIL/PdfImagePlugin.py
+Imaging/PIL/PixarImagePlugin.py
+Imaging/PIL/PngImagePlugin.py
+Imaging/PIL/PpmImagePlugin.py
+Imaging/PIL/PsdImagePlugin.py
+Imaging/PIL/PSDraw.py
+Imaging/PIL/SgiImagePlugin.py
+Imaging/PIL/SpiderImagePlugin.py
+Imaging/PIL/SunImagePlugin.py
+Imaging/PIL/TarIO.py
+Imaging/PIL/TgaImagePlugin.py
+Imaging/PIL/TiffImagePlugin.py
+Imaging/PIL/TiffTags.py
+Imaging/PIL/WalImageFile.py
+Imaging/PIL/WmfImagePlugin.py
+Imaging/PIL/XbmImagePlugin.py
+Imaging/PIL/XpmImagePlugin.py
+Imaging/PIL/XVThumbImagePlugin.py
+Imaging/PIL/__init__.py
+Imaging/Sane/CHANGES
+Imaging/Sane/demo_numarray.py
+Imaging/Sane/demo_pil.py
+Imaging/Sane/README
+Imaging/Sane/sane.py
+Imaging/Sane/sanedoc.txt
+Imaging/Sane/setup.py
+Imaging/Sane/_sane.c
+Imaging/Scripts/enhancer.py
+Imaging/Scripts/explode.py
+Imaging/Scripts/gifmaker.py
+Imaging/Scripts/image2py.py
+Imaging/Scripts/painter.py
+Imaging/Scripts/pilconvert.py
+Imaging/Scripts/pildriver.py
+Imaging/Scripts/pilfile.py
+Imaging/Scripts/pilfont.py
+Imaging/Scripts/pilprint.py
+Imaging/Scripts/player.py
+Imaging/Scripts/README
+Imaging/Scripts/thresholder.py
+Imaging/Scripts/viewer.py
+Imaging/Tk/booster.txt
+Imaging/Tk/install.txt
+Imaging/Tk/pilbitmap.txt
+Imaging/Tk/tkImaging.c
+icons/blur.svg
+icons/contour.svg
+
+icons/offset.svg
+icons/finedges.svg
+icons/left_top.svg
+
+
+icons/copy.svg
+icons/paste.svg
diff --git a/activity/activity-imageprocessor.svg b/activity/activity-imageprocessor.svg
index 7a011e3..d64349f 100644
--- a/activity/activity-imageprocessor.svg
+++ b/activity/activity-imageprocessor.svg
@@ -1,4 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY stroke_color "#666666">
+ <!ENTITY fill_color "#FFFFFF">
+ ]>
+
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
@@ -27,7 +32,7 @@
<defs
id="defs3071" />
<sodipodi:namedview
- pagecolor="#ffffff"
+ pagecolor="&fill_color;"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
@@ -51,17 +56,17 @@
y="7"
width="44"
height="36"
- style="fill:#FFFFFF;stroke:#010101;stroke-width:3"
+ style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:3"
id="rect3051" />
<polyline
points="15,7 25,1 35,7"
- style="fill:none;;stroke:#010101;stroke-width:1.25"
+ style="fill:none;;stroke:&stroke_color;;stroke-width:1.25"
id="polyline3053" />
<circle
cx="14"
cy="19"
r="4.5"
- style="fill:#010101;stroke:#010101;stroke-width:1.5"
+ style="fill:&stroke_color;;stroke:&stroke_color;;stroke-width:1.5"
id="circle3055"
sodipodi:cx="14"
sodipodi:cy="19"
@@ -70,19 +75,19 @@
transform="translate(13.166667,13.166667)" />
<polyline
points="3,36 16,32 26,35"
- style="fill:none;;stroke:#010101;stroke-width:2.5"
+ style="fill:none;;stroke:&stroke_color;;stroke-width:2.5"
id="polyline3057" />
<polyline
points="15,43 37,28 47,34 47,43"
- style="fill:#010101;stroke:#010101;stroke-width:3"
+ style="fill:&stroke_color;;stroke:&stroke_color;;stroke-width:3"
id="polyline3059" />
<polyline
points="22,41.5 35,30 27,41.5"
- style="fill:#FFFFFF;stroke:none;;stroke-width:0"
+ style="fill:&fill_color;;stroke:none;;stroke-width:0"
id="polyline3061" />
<path
sodipodi:type="star"
- style="fill:#000000"
+ style="fill:&stroke_color;"
id="path3111"
sodipodi:sides="5"
sodipodi:cx="21.5"
@@ -100,7 +105,7 @@
transform="translate(-0.66666667,0.66666667)" />
<path
sodipodi:type="star"
- style="fill:#000000"
+ style="fill:&stroke_color;"
id="path3113"
sodipodi:sides="5"
sodipodi:cx="26.833332"
@@ -118,7 +123,7 @@
transform="translate(1.6666667,-0.66666667)" />
<path
sodipodi:type="star"
- style="fill:#000000"
+ style="fill:&stroke_color;"
id="path3115"
sodipodi:sides="5"
sodipodi:cx="22.333332"
@@ -136,7 +141,7 @@
transform="translate(0,0.66666667)" />
<path
sodipodi:type="star"
- style="fill:#000000"
+ style="fill:&stroke_color;"
id="path3117"
sodipodi:sides="5"
sodipodi:cx="36"
@@ -154,7 +159,7 @@
transform="translate(0.66666667,-1.3333333)" />
<path
sodipodi:type="star"
- style="fill:#000000"
+ style="fill:&stroke_color;"
id="path3119"
sodipodi:sides="5"
sodipodi:cx="31.833332"
@@ -171,7 +176,7 @@
transform="translate(-0.16666667,-2.1666667)" />
<path
sodipodi:type="star"
- style="fill:#000000"
+ style="fill:&stroke_color;"
id="path3121"
sodipodi:sides="5"
sodipodi:cx="25.833332"
@@ -188,7 +193,7 @@
transform="translate(2,0.83333333)" />
<path
sodipodi:type="star"
- style="fill:#000000"
+ style="fill:&stroke_color;"
id="path3123"
sodipodi:sides="5"
sodipodi:cx="38.833332"
@@ -205,7 +210,7 @@
transform="translate(-18.5,5.6666666)" />
<path
sodipodi:type="star"
- style="fill:#000000"
+ style="fill:&stroke_color;"
id="path3127"
sodipodi:sides="5"
sodipodi:cx="40.5"
@@ -223,7 +228,7 @@
transform="translate(1.6666666,11.5)" />
<path
sodipodi:type="star"
- style="fill:#000000"
+ style="fill:&stroke_color;"
id="path3111-6"
sodipodi:sides="5"
sodipodi:cx="21.5"
@@ -241,7 +246,7 @@
transform="translate(-9.3785749,5.3828188)" />
<path
sodipodi:type="star"
- style="fill:#000000"
+ style="fill:&stroke_color;"
id="path3111-4"
sodipodi:sides="5"
sodipodi:cx="21.5"
@@ -259,7 +264,7 @@
transform="translate(-12.878575,0.04948551)" />
<path
sodipodi:type="star"
- style="fill:#000000"
+ style="fill:&stroke_color;"
id="path3111-1"
sodipodi:sides="5"
sodipodi:cx="21.5"
@@ -282,12 +287,12 @@
transform="scale(0.92,0.92)"
id="g3536">
<path
- style="fill:#ffffff;stroke:#010101;stroke-width:3"
+ style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:3"
inkscape:connector-curvature="0"
id="Left"
d="M 12.99,13.58 C 6.25,14.6 1.54,5.1 11.04,1.5 21.21,1.49 20.24,12.49 12.99,13.58 z M 17,50.37 c -0.21,10.84 -9.79,10.84 -10,0 0,0 0,-24.36 0,-24.36 0.01,-3.75 -0.58,-10.27 5.04,-10.27 4.52,0 14.97,10.11 16.12,14.17 1.08,3.83 -2.27,6.92 -6.16,6.18 -1.59,-0.3 -3.58,-1.51 -5,-2.28 0,0 0,16.56 0,16.56 z" />
<path
- style="fill:#010101;stroke:#ffffff;stroke-width:3"
+ style="fill:&stroke_color;;stroke:&fill_color;;stroke-width:3"
inkscape:connector-curvature="0"
id="Right"
d="M 47.98,13.8 C 41.36,14.71 35.84,4.88 46.01,1.5 c 10.41,0.26 8.5,11.4 1.97,12.3 z M 30.84,29.99 c 1.14,-4.06 11.61,-14.18 16.12,-14.18 5.28,0 5.02,5.68 5.04,9.31 0,0 0,24.36 0,24.36 -0.08,10.9 -6.33,10.31 -9.15,6.59 C 40.77,53.32 41,48.85 41,45.58 c 0,0 0,-11.69 0,-11.69 -8.15,5.58 -11.2,-0.18 -10.16,-3.9 z" />
diff --git a/activity/activity.info b/activity/activity.info
index 274972e..4ca109b 100644
--- a/activity/activity.info
+++ b/activity/activity.info
@@ -1,19 +1,8 @@
[Activity]
-sweet = imageprocessor
name = Image Processor
-summary = The Image Processor activity is a simple and fast image processor tool
-description = It has features one would expect of a standard image processor,
- like filtering, merging, watermarkin text and images over images, etc and also image viewer functions.
-homepage = http://wiki.sugarlabs.org/go/Activities/Image_Processor
license = GPLv2+
-
icon = activity-imageprocessor
exec = sugar-activity ImageProcessorActivity.ImageProcessorActivity
mime_types = image/bmp;image/gif;image/jpeg;image/png;image/tiff;image/svg+xml
-
-version = 1
-stability = testing
-
-# support original activity.info fields
-activity_version = 1
+activity_version = 4
bundle_id = org.laptop.ImageProcessorActivity
diff --git a/activity/activity.info.rtf b/activity/activity.info.rtf
new file mode 100644
index 0000000..a393820
--- /dev/null
+++ b/activity/activity.info.rtf
Binary files differ
diff --git a/dist/ImageProcessor-4.xo b/dist/ImageProcessor-4.xo
new file mode 100644
index 0000000..6fee87f
--- /dev/null
+++ b/dist/ImageProcessor-4.xo
Binary files differ
diff --git a/icons/blur.svg b/icons/blur.svg
index de2a505..a3a9000 100644
--- a/icons/blur.svg
+++ b/icons/blur.svg
@@ -1,6 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
@@ -9,38 +7,14 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16px"
- height="16px"
- id="svg3043"
+ width="22"
+ height="22"
+ id="svg2"
version="1.1"
inkscape:version="0.48.0 r9654"
sodipodi:docname="blur.svg">
- <defs
- id="defs3045" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="22.197802"
- inkscape:cx="7.7888027"
- inkscape:cy="9.3382944"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
- inkscape:window-width="1366"
- inkscape:window-height="701"
- inkscape:window-x="0"
- inkscape:window-y="0"
- inkscape:window-maximized="1"
- inkscape:snap-smooth-nodes="true"
- inkscape:object-nodes="false"
- inkscape:snap-bbox="true" />
<metadata
- id="metadata3048">
+ id="metadata976">
<rdf:RDF>
<cc:Work
rdf:about="">
@@ -50,42 +24,196 @@
</cc:Work>
</rdf:RDF>
</metadata>
+ <defs
+ id="defs974" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1366"
+ inkscape:window-height="701"
+ id="namedview972"
+ showgrid="false"
+ inkscape:zoom="13.636364"
+ inkscape:cx="11"
+ inkscape:cy="14.199441"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" />
+ <path
+ d="m 9.8211464,2.0819197 c 4.8411266,0.1802542 8.6181296,4.287987 8.4361716,9.1748753 -0.181958,4.88689 -4.253974,8.702372 -9.0951006,8.522117 C 4.3210904,19.598658 0.54408736,15.490926 0.72604536,10.604037 0.90800336,5.7171484 4.9800194,1.9016655 9.8211464,2.0819197 l 0,0 z"
+ id="path2387"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:1.523247;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 12.796131,2.0048372 c 4.841126,0.1802542 8.61813,4.2879871 8.436172,9.1748758 -0.181958,4.88689 -4.253975,8.702372 -9.095101,8.522117 C 7.2960754,19.521576 3.5190724,15.413844 3.7010304,10.526955 3.8829884,5.640066 7.9550044,1.824583 12.796131,2.0048372 l 0,0 z"
+ id="path2387-2"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:1.523247;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(0.43287093,0.01611749,-0.01626984,0.43696277,-1.5691458,-1.885025)"
+ id="g2937">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 27.567493,45.252146 c -0.46948,0 -0.933016,-0.02903 -1.389761,-0.08296 l 1.178368,1.948634 1.161389,-1.918769 c -0.314968,0.02489 -0.629086,0.05309 -0.949996,0.05309 z"
+ id="path3003"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 38.317981,14.929279 c -1.837168,0 -3.360217,1.289964 -3.68707,2.992219 1.578232,1.115757 2.934884,2.584076 3.968928,4.320343 1.939893,-0.142684 3.475677,-1.709721 3.475677,-3.641764 0,-2.027442 -1.682656,-3.670798 -3.757535,-3.670798 z"
+ id="path3007"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 38.787461,38.290488 c -1.039138,1.851575 -2.42805,3.426908 -4.072502,4.609029 0.442312,1.546298 1.878767,2.686942 3.603022,2.686942 2.07403,0 3.757535,-1.642527 3.757535,-3.669969 0,-1.870656 -1.437304,-3.397874 -3.288055,-3.626002 z"
+ id="path3009"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 16.340734,38.277215 c -1.912727,0.170889 -3.41625,1.724653 -3.41625,3.639275 0,2.026612 1.680958,3.669969 3.755837,3.669969 1.752271,0 3.212497,-1.177974 3.626793,-2.764091 -1.598607,-1.174655 -2.950165,-2.728419 -3.96638,-4.545153 z"
+ id="path3011"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 20.375881,18.007772 c -0.291196,-1.744563 -1.828678,-3.078493 -3.69556,-3.078493 -2.074879,0 -3.755837,1.643356 -3.755837,3.669968 0,1.97601 1.601155,3.575399 3.603872,3.655037 1.006876,-1.694789 2.319381,-3.139051 3.847525,-4.246512 z"
+ id="path3013"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 27.567493,15.62362 c 1.619832,0 3.164955,0.340948 4.599711,0.935742 0.629086,-0.892605 1.000085,-1.971862 1.000085,-3.138221 0,-3.058584 -2.537567,-5.5389654 -5.668563,-5.5389654 -3.130146,0 -5.667713,2.4803814 -5.667713,5.5389654 0,1.18461 0.383734,2.280457 1.032345,3.180529 1.463622,-0.62134 3.04525,-0.97805 4.704135,-0.97805 z"
+ id="path3015"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3017"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z"
+ id="path3019"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+ <g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3021"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z"
+ id="path3023"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z"
+ id="path3025"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z"
+ id="path3027"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z"
+ id="path3029"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z"
+ id="path3031"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z"
+ id="path3033"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+ </g>
<g
- id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <text
- xml:space="preserve"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.4415842"
- y="14.693564"
- id="text3821"
- sodipodi:linespacing="125%"><tspan
- sodipodi:role="line"
- id="tspan3823"
- x="1.4415842"
- y="14.693564" /></text>
- <text
- xml:space="preserve"
- style="font-size:14.29584885px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="3.0767288"
- y="13.203192"
- id="text4470"
- sodipodi:linespacing="125%"
- transform="scale(1.057428,0.94569086)"><tspan
- sodipodi:role="line"
- id="tspan4472"
- x="3.0767288"
- y="13.203192">B</tspan></text>
+ transform="matrix(0.43287093,0.01611749,-0.01626984,0.43696277,0.59917219,-1.9642571)"
+ id="g2937-8"
+ inkscape:transform-center-x="2.018672"
+ inkscape:transform-center-y="-2.861304">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 27.567493,45.252146 c -0.46948,0 -0.933016,-0.02903 -1.389761,-0.08296 l 1.178368,1.948634 1.161389,-1.918769 c -0.314968,0.02489 -0.629086,0.05309 -0.949996,0.05309 z"
+ id="path3003-9"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 38.317981,14.929279 c -1.837168,0 -3.360217,1.289964 -3.68707,2.992219 1.578232,1.115757 2.934884,2.584076 3.968928,4.320343 1.939893,-0.142684 3.475677,-1.709721 3.475677,-3.641764 0,-2.027442 -1.682656,-3.670798 -3.757535,-3.670798 z"
+ id="path3007-2"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 38.787461,38.290488 c -1.039138,1.851575 -2.42805,3.426908 -4.072502,4.609029 0.442312,1.546298 1.878767,2.686942 3.603022,2.686942 2.07403,0 3.757535,-1.642527 3.757535,-3.669969 0,-1.870656 -1.437304,-3.397874 -3.288055,-3.626002 z"
+ id="path3009-6"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 16.340734,38.277215 c -1.912727,0.170889 -3.41625,1.724653 -3.41625,3.639275 0,2.026612 1.680958,3.669969 3.755837,3.669969 1.752271,0 3.212497,-1.177974 3.626793,-2.764091 -1.598607,-1.174655 -2.950165,-2.728419 -3.96638,-4.545153 z"
+ id="path3011-6"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
- style="fill:#ffffff"
- d="m 4.7434561,7.6877716 0,-4.8012145 1.8808169,1.269e-4 c 1.0949068,7.38e-5 2.0502346,0.020888 2.2862624,0.049812 1.1783266,0.1443982 1.9696656,0.5551486 2.3068066,1.1973649 0.222872,0.4245466 0.312815,0.9678866 0.237876,1.4369908 -0.139015,0.8701982 -0.795937,1.5048331 -1.7783617,1.7180272 -0.2137815,0.046392 -0.3383506,0.095386 -0.3383506,0.133076 0,0.032808 0.045613,0.059703 0.1013614,0.059765 0.1853999,2.253e-4 0.9342899,0.2223851 1.2089869,0.3586765 0.764587,0.3793511 1.122325,0.9740406 1.122325,1.8657095 0,1.2082979 -0.648365,2.0955939 -1.8346276,2.5107139 -0.6271878,0.219477 -0.7717147,0.231467 -3.0419814,0.252365 l -2.1511139,0.0198 0,-4.8012144 z m 4.1451781,3.7186674 c 0.6667722,-0.143879 1.0845361,-0.427723 1.3132978,-0.892302 0.143881,-0.292199 0.150188,-0.326806 0.150188,-0.8240906 0,-0.4654889 -0.01214,-0.5449751 -0.117611,-0.769855 C 10.089928,8.6119149 9.8506163,8.373239 9.5376457,8.2251802 9.0650315,8.0015982 8.8231211,7.9696743 7.4126393,7.9447543 l -1.317698,-0.023281 0,1.7908102 0,1.7908097 1.2951733,-0.02639 c 0.7123453,-0.01451 1.3866791,-0.04613 1.4985196,-0.07027 z M 8.7432491,6.8943733 C 9.4441932,6.7806254 9.8776118,6.4741177 10.031607,5.9832637 10.152952,5.5964818 10.121942,4.9662949 9.9667391,4.6650044 9.7626382,4.2687904 9.3146263,4.0268615 8.5951888,3.9243598 8.4217483,3.8996489 7.7882396,3.8790293 7.1873918,3.8785386 l -1.0924505,-8.924e-4 0,1.5316832 0,1.5316831 1.1825495,-3.423e-4 C 7.927893,6.9404809 8.5874843,6.9196485 8.7432491,6.8943712 l 0,2.1e-6 z"
- id="path3024"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ d="m 20.375881,18.007772 c -0.291196,-1.744563 -1.828678,-3.078493 -3.69556,-3.078493 -2.074879,0 -3.755837,1.643356 -3.755837,3.669968 0,1.97601 1.601155,3.575399 3.603872,3.655037 1.006876,-1.694789 2.319381,-3.139051 3.847525,-4.246512 z"
+ id="path3013-4"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
- style="fill:#f5f5f5"
- d="m 4.7434561,7.6792014 0,-4.7926443 0.7545793,0.00315 c 1.6571787,0.00692 3.5903556,0.081128 3.887415,0.1492244 0.9154366,0.2098511 1.5123616,0.5760065 1.7908566,1.0985168 0.260254,0.488285 0.34335,1.0956903 0.215565,1.5756973 -0.205124,0.7705148 -0.694404,1.2354013 -1.5881284,1.5089504 -0.2558807,0.07832 -0.4652379,0.1665799 -0.4652379,0.1961346 0,0.06173 0.1009875,0.1084247 0.234489,0.1084247 0.1473938,0 1.0133723,0.3036224 1.2328793,0.4322626 0.320868,0.1880407 0.598078,0.4890642 0.750679,0.815165 0.120657,0.2578377 0.142829,0.3633395 0.160672,0.7645225 0.02443,0.5491928 -0.03774,0.9211418 -0.217132,1.2991888 -0.320832,0.676109 -0.843795,1.101548 -1.7206657,1.399791 -0.4304949,0.14642 -1.1075693,0.190637 -3.2903028,0.214875 l -1.7456684,0.01938 0,-4.7926436 z m 2.7845642,3.8116636 c 1.1247284,-0.03661 1.364956,-0.05673 1.6206761,-0.135714 0.3822094,-0.118052 0.6277508,-0.262478 0.8335816,-0.490309 0.299426,-0.331428 0.363733,-0.5098 0.383619,-1.0640648 0.0099,-0.2752989 -0.0038,-0.5766066 -0.03066,-0.676435 C 10.261953,8.8521842 10.039849,8.5339955 9.8093307,8.3709203 9.3226789,8.0266493 8.8951945,7.9540957 7.1198175,7.9144495 l -1.0248762,-0.022887 0,1.8222498 c 0,1.4283567 0.012172,1.8220107 0.056312,1.8211437 0.030971,-6.08e-4 0.6505167,-0.02045 1.3767671,-0.04409 l 0,0 z M 9.1708913,6.8165429 C 9.6320825,6.6450119 9.9018403,6.3938434 10.039602,6.0076951 10.115382,5.7952847 10.122081,5.1142082 10.051161,4.8325599 9.9730154,4.5222142 9.6340629,4.2008402 9.2484067,4.0714364 8.7386863,3.900404 8.5082929,3.8776462 7.2865358,3.8776462 l -1.1915945,0 0,1.5350772 0,1.5350772 1.407797,-0.017212 c 1.3055295,-0.015961 1.4267103,-0.024246 1.668153,-0.114046 l 0,0 z"
- id="path3097"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ d="m 27.567493,15.62362 c 1.619832,0 3.164955,0.340948 4.599711,0.935742 0.629086,-0.892605 1.000085,-1.971862 1.000085,-3.138221 0,-3.058584 -2.537567,-5.5389654 -5.668563,-5.5389654 -3.130146,0 -5.667713,2.4803814 -5.667713,5.5389654 0,1.18461 0.383734,2.280457 1.032345,3.180529 1.463622,-0.62134 3.04525,-0.97805 4.704135,-0.97805 z"
+ id="path3015-9"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3017-5"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z"
+ id="path3019-0"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+ <g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3021-4"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z"
+ id="path3023-8"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z"
+ id="path3025-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z"
+ id="path3027-1"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z"
+ id="path3029-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z"
+ id="path3031-2"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z"
+ id="path3033-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
</g>
</svg>
diff --git a/icons/contour.svg b/icons/contour.svg
index 3ca6972..9f686ba 100644
--- a/icons/contour.svg
+++ b/icons/contour.svg
@@ -9,73 +9,262 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16px"
- height="16px"
- id="svg3043"
- version="1.1"
+ version="1.0"
+ width="45"
+ height="45"
+ viewBox="0 0 55 55"
+ id="svg2"
+ xml:space="preserve"
inkscape:version="0.48.0 r9654"
- sodipodi:docname="contour.svg">
- <defs
- id="defs3045" />
- <sodipodi:namedview
- id="base"
+ sodipodi:docname="contour.svg"><metadata
+ id="metadata24"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
inkscape:pageshadow="2"
- inkscape:zoom="22.197802"
- inkscape:cx="7.7888027"
- inkscape:cy="8.2141213"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
inkscape:window-width="1366"
inkscape:window-height="701"
+ id="namedview22"
+ showgrid="false"
+ inkscape:zoom="6.6666667"
+ inkscape:cx="22.5"
+ inkscape:cy="34.5"
inkscape:window-x="0"
inkscape:window-y="0"
- inkscape:window-maximized="1" />
- <metadata
- id="metadata3048">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <path
- sodipodi:type="arc"
- style="fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- id="path3276"
- sodipodi:cx="14.55099"
- sodipodi:cy="8.6118813"
- sodipodi:rx="9.6405945"
- sodipodi:ry="6.1267328"
- d="m 24.191585,8.6118813 a 9.6405945,6.1267328 0 1 1 -19.2811894,0 9.6405945,6.1267328 0 1 1 19.2811894,0 z"
- transform="matrix(0.77310759,0,0,0.78636047,1.1841824,1.3668185)" />
- <path
- style="fill:#f5f5f5"
- d="m 11.388258,12.498201 c -0.07433,-0.01031 -0.297327,-0.04024 -0.495544,-0.0665 C 9.6328073,12.264768 8.2444115,11.761952 7.3009299,11.130913 6.8583989,10.83493 6.2815595,10.293311 6.0230798,9.9310839 4.3197023,7.5440142 6.2925332,4.7867668 10.30707,3.943738 c 1.781847,-0.3741772 4.007612,-0.215719 5.676238,0.4041065 1.006015,0.3736932 1.838701,0.8971804 2.471883,1.5540058 2.394173,2.4835756 0.317584,5.6870727 -4.206289,6.4889267 -0.455085,0.08066 -0.770544,0.102341 -1.644307,0.112994 -0.594654,0.0073 -1.142005,0.0047 -1.216337,-0.0056 z"
- id="path3071"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 11.861278,13.307426 C 10.69765,13.227336 9.8507744,13.070752 8.9330601,12.766011 6.0951211,11.823626 4.3840023,9.8124104 4.6507228,7.7326351 4.7741216,6.7704223 5.202267,5.9811486 6.0368877,5.1772797 6.9251019,4.3217919 8.3147893,3.6107467 9.766476,3.2690046 c 1.007398,-0.237152 1.35864,-0.2720881 2.70297,-0.2688501 1.15742,0.00279 1.315226,0.012777 1.914604,0.121198 2.792051,0.505051 4.88149,1.8803782 5.594488,3.682447 0.593409,1.4998138 0.170063,3.0766059 -1.159358,4.3181385 -1.19748,1.118314 -3.075837,1.907785 -5.043298,2.11969 -0.485881,0.05233 -1.569293,0.08957 -1.914604,0.0658 l 0,0 z m 1.747444,-0.784795 c 2.588495,-0.281096 4.766036,-1.471209 5.566796,-3.0424742 0.224604,-0.440722 0.314668,-0.8166903 0.317375,-1.3248722 0.0028,-0.5174048 -0.06291,-0.808818 -0.28931,-1.2839109 C 18.271733,4.9159178 15.358475,3.613431 12.131575,3.7095534 10.187822,3.7674535 8.5938267,4.2298981 7.2539083,5.1246452 6.5042996,5.6252057 5.9602319,6.2286829 5.6436656,6.9107184 c -0.209435,0.4512232 -0.2740249,0.747217 -0.2735408,1.253546 0.00118,1.2318562 0.7929537,2.3577556 2.2855816,3.2500806 0.8128676,0.485949 2.1886462,0.931277 3.2820566,1.062373 0.222995,0.02674 0.456126,0.05593 0.518069,0.06488 0.262189,0.03787 1.750191,0.02476 2.15289,-0.01897 z"
- id="path3073"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#f5f5f5"
- d="M 11.343209,13.245117 C 9.5937341,13.047645 8.1056839,12.547838 6.9058324,11.754689 6.371566,11.401518 5.5996242,10.644014 5.2940686,10.173071 4.333312,8.692286 4.4609788,7.0416268 5.644523,5.6418912 6.5242567,4.6014616 7.9776713,3.7613648 9.6390341,3.3330005 10.656527,3.0706509 10.898273,3.0460473 12.469446,3.0449358 l 1.441584,-0.00102 0.675743,0.1437076 c 3.06324,0.6514473 5.091652,2.1976978 5.542729,4.2251995 0.121327,0.5453416 0.07646,1.3228244 -0.106086,1.838493 -0.175145,0.4947481 -0.348625,0.8049689 -0.714633,1.2779159 -1.015785,1.312573 -3.041351,2.333074 -5.262604,2.651352 -0.557056,0.07982 -2.216538,0.119439 -2.70297,0.06453 l 0,0 z m 2.65792,-0.761604 C 16.765411,12.076606 18.883573,10.69757 19.40378,8.966101 19.516955,8.5894051 19.542459,7.9263467 19.458841,7.5345759 19.213513,6.3851352 18.209412,5.3106395 16.714948,4.5983127 15.491619,4.0152208 14.335659,3.7506808 12.823067,3.7076607 c -1.40431,-0.03994 -2.56562,0.113516 -3.6854803,0.4870019 -1.6873215,0.562741 -2.9205738,1.5045897 -3.4796228,2.6574276 -0.2369382,0.4885999 -0.291032,0.7272059 -0.2911923,1.284439 -2.658e-4,0.9183702 0.2931535,1.5643927 1.0650169,2.3448648 0.4480104,0.453008 1.021282,0.873535 1.555232,1.140851 0.6916321,0.346258 1.9286198,0.723796 2.8072965,0.85681 0.792543,0.119975 2.406819,0.122219 3.206812,0.0045 l 0,-2e-6 z"
- id="path3203"
- inkscape:connector-curvature="0" />
- </g>
-</svg>
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" /><defs
+ id="defs12">
+
+</defs><path
+ d=""
+ id="path2385"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:1.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path
+ style="fill:#000000"
+ d=""
+ id="path3234"
+ inkscape:connector-curvature="0"
+ transform="scale(1.2222222,1.2222222)" /><path
+ style="fill:#000000"
+ d=""
+ id="path3242"
+ inkscape:connector-curvature="0"
+ transform="scale(1.2222222,1.2222222)" /><path
+ style="fill:#000000"
+ d=""
+ id="path3244"
+ inkscape:connector-curvature="0"
+ transform="scale(1.2222222,1.2222222)" /><path
+ style="fill:#ffffff"
+ d=""
+ id="path3256"
+ inkscape:connector-curvature="0"
+ transform="scale(1.2222222,1.2222222)" /><path
+ style="fill:#ffffff"
+ d=""
+ id="path3038"
+ inkscape:connector-curvature="0"
+ transform="scale(1.2222222,1.2222222)" /><path
+ d="m 52.616666,27.5 c 0,13.669047 -11.080953,24.75 -24.75,24.75 C 14.19762,52.25 3.1166668,41.169047 3.1166668,27.5 c 0,-13.669047 11.0809532,-24.7500003 24.7499992,-24.7500003 13.669047,0 24.75,11.0809533 24.75,24.7500003 l 0,0 z"
+ id="path2387"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:4.27777815;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><g
+ transform="matrix(1.0000763,0.02983471,-0.01559181,0.81866712,1.6018916,3.1607662)"
+ id="g2937"><path
+ d="m 27.567493,45.252146 c -0.46948,0 -0.933016,-0.02903 -1.389761,-0.08296 l 1.178368,1.948634 1.161389,-1.918769 c -0.314968,0.02489 -0.629086,0.05309 -0.949996,0.05309 z"
+ id="path3003"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 38.317981,14.929279 c -1.837168,0 -3.360217,1.289964 -3.68707,2.992219 1.578232,1.115757 2.934884,2.584076 3.968928,4.320343 1.939893,-0.142684 3.475677,-1.709721 3.475677,-3.641764 0,-2.027442 -1.682656,-3.670798 -3.757535,-3.670798 z"
+ id="path3007"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 38.787461,38.290488 c -1.039138,1.851575 -2.42805,3.426908 -4.072502,4.609029 0.442312,1.546298 1.878767,2.686942 3.603022,2.686942 2.07403,0 3.757535,-1.642527 3.757535,-3.669969 0,-1.870656 -1.437304,-3.397874 -3.288055,-3.626002 z"
+ id="path3009"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 16.340734,38.277215 c -1.912727,0.170889 -3.41625,1.724653 -3.41625,3.639275 0,2.026612 1.680958,3.669969 3.755837,3.669969 1.752271,0 3.212497,-1.177974 3.626793,-2.764091 -1.598607,-1.174655 -2.950165,-2.728419 -3.96638,-4.545153 z"
+ id="path3011"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 20.375881,18.007772 c -0.291196,-1.744563 -1.828678,-3.078493 -3.69556,-3.078493 -2.074879,0 -3.755837,1.643356 -3.755837,3.669968 0,1.97601 1.601155,3.575399 3.603872,3.655037 1.006876,-1.694789 2.319381,-3.139051 3.847525,-4.246512 z"
+ id="path3013"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 27.567493,15.62362 c 1.619832,0 3.164955,0.340948 4.599711,0.935742 0.629086,-0.892605 1.000085,-1.971862 1.000085,-3.138221 0,-3.058584 -2.537567,-5.5389654 -5.668563,-5.5389654 -3.130146,0 -5.667713,2.4803814 -5.667713,5.5389654 0,1.18461 0.383734,2.280457 1.032345,3.180529 1.463622,-0.62134 3.04525,-0.97805 4.704135,-0.97805 z"
+ id="path3015"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3017"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z"
+ id="path3019"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /></g><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3021"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z"
+ id="path3023"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z"
+ id="path3025"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z"
+ id="path3027"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z"
+ id="path3029"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z"
+ id="path3031"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z"
+ id="path3033"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /></g></g><path
+ style="fill:#000000"
+ d="m 27.008361,40.215492 c -2.871788,-0.438968 -6.013658,-2.012765 -7.761706,-3.887918 -1.120526,-1.202005 -2.215297,-3.115522 -2.704648,-4.727375 -2.050594,-6.754373 3.532564,-13.730784 11.303808,-14.124617 6.235783,-0.31602 12.084094,3.96158 13.24389,9.686907 1.318563,6.509063 -4.271342,12.861844 -11.55973,13.137332 -0.868653,0.03283 -2.003379,-0.0051 -2.521614,-0.08433 z m 6.057799,-4.036101 c 0.709955,-0.302087 1.287145,-0.621924 1.282643,-0.71075 -0.0045,-0.08883 -0.256722,-0.382081 -0.560492,-0.65168 -0.303768,-0.2696 -0.557434,-0.591374 -0.563702,-0.715053 -0.0063,-0.123675 0.339998,0.09694 0.769481,0.490264 l 0.780879,0.715138 0.788825,-1.027191 c 0.433856,-0.564956 1.022684,-1.535455 1.308511,-2.156665 0.468216,-1.01761 0.508641,-1.347426 0.408163,-3.330098 -0.0991,-1.955485 -0.179746,-2.320049 -0.72393,-3.272724 -0.824688,-1.443732 -2.238123,-2.921281 -3.401029,-3.55531 -0.94333,-0.51431 -3.328727,-1.161054 -3.509677,-0.951565 -0.0512,0.05928 -0.217552,1.034821 -0.369667,2.167873 l -0.276573,2.060094 0.0074,-2.277346 0.0074,-2.277344 -0.706238,0.151946 c -0.388429,0.08357 -1.175078,0.239282 -1.748106,0.346039 -2.05988,0.383759 -4.504484,2.062674 -5.139011,3.52939 -0.168044,0.388434 -0.425489,0.811606 -0.572101,0.940381 -0.453412,0.398249 -0.830344,2.996913 -0.644919,4.446237 0.411189,3.213957 3.219061,6.114874 6.619921,6.839283 1.302402,0.277422 4.805452,-0.149602 6.242145,-0.76091 l 0,0 z"
+ id="path3216"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="m 16.517589,39.574702 c -1.631148,-0.654925 -1.929817,-2.039081 -0.61678,-2.858409 l 0.769656,-0.48026 1.424378,1.472208 1.424378,1.472208 -0.546494,0.293527 c -0.715742,0.384435 -1.652787,0.422879 -2.455138,0.100722 z"
+ id="path3218"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="m 16.573251,20.266081 c -1.412036,-0.802827 -1.551983,-1.805163 -0.37256,-2.668386 0.811073,-0.593628 2.461968,-0.612653 3.39676,-0.03915 l 0.628377,0.385519 -0.475453,0.365202 c -0.261499,0.200865 -0.941493,0.803959 -1.511097,1.340214 l -1.035645,0.975009 -0.630382,-0.358411 0,0 z"
+ id="path3220"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="M 31.884891,15.992686 C 31.207987,15.785258 29.9787,15.730916 27.761426,15.810397 l -3.159051,0.113246 -0.107814,-0.874983 c -0.215543,-1.74947 1.539496,-3.213378 4.00826,-3.343346 2.997469,-0.157815 5.347106,1.867707 4.766343,4.10884 -0.149183,0.575688 -0.106277,0.570155 -1.384276,0.178545 z"
+ id="path3222"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="m 38.951868,19.853821 c -1.486417,-1.515 -1.476562,-1.75011 0.08444,-2.014789 2.491501,-0.42245 4.264768,1.895889 2.29526,3.000787 -0.384986,0.215979 -0.780953,0.385155 -0.879924,0.375951 -0.09896,-0.0093 -0.773873,-0.622082 -1.49978,-1.361949 z"
+ id="path3224"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="m 31.584264,25.730643 -1.15025,-0.782242 0.07382,-1.106878 c 0.0406,-0.608783 0.131708,-1.178819 0.202467,-1.266745 0.253492,-0.31499 2.307992,0.839919 3.344067,1.87982 0.580741,0.582886 1.060023,1.141319 1.065073,1.240961 0.0122,0.240722 -0.367858,0.403455 -1.470759,0.629754 -0.829436,0.170189 -1.020763,0.115082 -2.064412,-0.59467 l 0,0 z"
+ id="path3226"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="m 24.23892,25.432149 c -1.366984,-0.633345 -1.320063,-0.5778 -0.920498,-1.089718 0.455064,-0.58302 2.468093,-1.637 3.602826,-1.886362 0.892246,-0.196075 0.913511,-0.187276 0.80786,0.334258 -0.05968,0.294599 -0.09607,0.8066 -0.08087,1.137784 0.02351,0.511226 -0.15039,0.707976 -1.151402,1.303023 l -1.179034,0.700875 -1.078877,-0.499861 0,0 z"
+ id="path3228"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="m 21.978718,31.528091 c -0.502488,-1.005842 -0.596336,-1.425293 -0.557995,-2.493955 0.02535,-0.706608 0.101603,-1.390544 0.169447,-1.519861 0.07822,-0.149122 0.552494,-0.04183 1.296667,0.293426 1.091837,0.49184 1.20631,0.615406 1.64842,1.779341 l 0.475107,1.250795 -1.019181,0.939874 c -0.560549,0.51693 -1.106747,0.944311 -1.213776,0.949735 -0.107029,0.0054 -0.466439,-0.534286 -0.798689,-1.199355 z"
+ id="path3230"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="m 28.429915,30.481452 c -0.619726,-0.08715 -0.772517,-0.241664 -1.167326,-1.180406 -0.249848,-0.594064 -0.454744,-1.087942 -0.455322,-1.097505 -5.74e-4,-0.0095 0.447356,-0.265904 0.995412,-0.569644 l 0.996464,-0.552254 1.077274,0.667434 1.077276,0.667435 -0.483094,1.088403 c -0.506261,1.140591 -0.589853,1.180595 -2.040684,0.976537 l 0,0 z"
+ id="path3232"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="m 33.586203,32.223178 -0.899795,-1.014033 0.36636,-0.991629 c 0.201498,-0.545397 0.402183,-1.033102 0.445968,-1.083793 0.04377,-0.05068 0.646581,-0.246325 1.339548,-0.434743 l 1.259941,-0.342581 0.04392,0.908093 c 0.05446,1.123954 -1.040169,3.941503 -1.541103,3.966889 -0.06327,0.0032 -0.519944,-0.450485 -1.01483,-1.008204 z"
+ id="path3236"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="m 26.469702,35.428891 c -0.687158,-0.199183 -1.298429,-0.4085 -1.358377,-0.465146 -0.05995,-0.05665 0.389537,-0.539316 0.998858,-1.072598 l 1.107854,-0.969601 1.596326,0.07003 c 1.583531,0.06947 1.603535,0.0781 2.495569,1.076392 1.089373,1.21914 1.029079,1.273692 -1.701289,1.539274 -1.472178,0.143195 -2.165533,0.103838 -3.138941,-0.178353 z"
+ id="path3238"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="m 38.405293,40.261566 c -0.984989,-0.31644 -1.049107,-0.633728 -0.245466,-1.214701 0.369019,-0.266775 0.976128,-0.850801 1.349131,-1.297839 0.676269,-0.810501 0.679977,-0.811818 1.31366,-0.467227 0.788438,0.428747 1.124835,0.981419 1.000836,1.644294 -0.199662,1.067363 -2.028542,1.781905 -3.418161,1.335473 l 0,0 z"
+ id="path3240"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 26.263201,36.527387 c -1.319168,-0.378395 -2.70318,-1.12049 -2.828582,-1.516659 -0.03779,-0.11943 0.702766,-0.889247 1.645708,-1.710708 l 1.714443,-1.493562 1.735732,0.0618 c 0.954651,0.034 1.901815,0.103722 2.104806,0.154966 0.351996,0.08886 3.276622,3.15141 3.291593,3.446822 0.01791,0.353486 -2.536086,1.084567 -4.36735,1.250153 -1.575172,0.142427 -2.269144,0.1019 -3.29635,-0.192807 z m 5.127162,-0.945302 c 0.57778,-0.160687 1.046422,-0.372807 1.041426,-0.471392 -0.005,-0.09858 -0.431748,-0.652377 -0.948339,-1.230648 l -0.939253,-1.051403 -1.75594,-0.05974 -1.755939,-0.05974 -1.235227,1.101434 -1.235228,1.101434 0.622488,0.307601 c 1.583992,0.782722 4.154898,0.932875 6.206012,0.362458 z"
+ id="path3246"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 33.395738,33.569979 c -2.232364,-2.202568 -2.115173,-1.863927 -1.315634,-3.801652 l 0.698139,-1.691981 2.04423,-0.535561 c 1.12433,-0.294555 2.095745,-0.486883 2.158701,-0.427393 0.24729,0.233676 0.237205,2.878699 -0.01516,3.975937 -0.24533,1.066639 -1.626457,3.398848 -2.134024,3.60357 -0.116392,0.04695 -0.762707,-0.458369 -1.436249,-1.12292 z m 1.984153,-0.92919 c 0.287356,-0.439024 0.630435,-1.176208 0.7624,-1.638185 0.257837,-0.902633 0.254355,-2.941669 -0.005,-2.915761 -0.33745,0.03371 -2.783128,0.749955 -2.826087,0.827648 -0.02504,0.04527 -0.245818,0.616544 -0.490627,1.269474 l -0.445108,1.187148 1.085935,1.041807 c 0.597264,0.572995 1.1557,1.038273 1.24097,1.033952 0.08528,-0.0043 0.390144,-0.367058 0.677498,-0.806083 l 0,0 z"
+ id="path3248"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 28.006457,31.639377 -0.980747,-0.03194 -0.738555,-1.881956 c -0.406208,-1.035077 -0.676389,-1.94637 -0.600405,-2.025095 0.07599,-0.07873 0.798717,-0.54554 1.606068,-1.037368 l 1.467914,-0.894229 1.705692,1.068181 c 0.93813,0.587501 1.736586,1.091053 1.774347,1.119008 0.03776,0.02795 -0.276522,0.872851 -0.698401,1.877549 l -0.767056,1.82672 -0.894055,0.0055 c -0.491729,0.0031 -1.335392,-0.0088 -1.874802,-0.02641 l 0,0 z m 2.725371,-2.069698 0.504996,-1.235852 -1.137443,-0.717744 c -0.625595,-0.39476 -1.263897,-0.711337 -1.418448,-0.703504 -0.154553,0.0078 -0.690202,0.294444 -1.190331,0.636916 -0.97655,0.668706 -0.962116,0.552258 -0.285826,2.306049 0.250709,0.650152 0.409379,0.770446 1.120592,0.84957 1.84801,0.205591 1.860988,0.199467 2.40646,-1.135435 l 0,0 z"
+ id="path3250"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 30.99869,26.621652 c -1.772812,-1.256716 -1.744583,-1.181577 -1.440823,-3.835123 0.176475,-1.541643 0.182585,-1.55308 0.807162,-1.510732 1.982421,0.134414 4.67443,2.113547 5.891414,4.331294 l 0.599394,1.092291 -0.780499,0.187863 c -0.429272,0.103339 -1.390301,0.338786 -2.135615,0.52325 l -1.355116,0.335387 -1.585917,-1.12423 0,0 z m 4.182516,-0.451159 c 0.356404,-0.159043 0.337154,-0.237739 -0.28129,-1.149923 -0.770175,-1.135975 -1.734709,-1.881221 -3.19583,-2.469247 -1.078788,-0.434159 -1.3866,-0.314894 -1.358112,0.526207 0.0061,0.181708 -0.02735,0.6918 -0.07446,1.133541 -0.08149,0.764156 -0.02861,0.844901 1.08875,1.662335 1.133247,0.829065 1.214059,0.852312 2.306375,0.663494 0.622589,-0.10762 1.304141,-0.272505 1.514563,-0.366406 z"
+ id="path3252"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 23.223478,26.183974 c -0.954905,-0.492537 -1.709218,-1.01873 -1.679801,-1.171794 0.0891,-0.463646 1.264525,-1.761914 2.134643,-2.35774 0.951377,-0.651469 2.668251,-1.27978 4.090358,-1.49692 1.140907,-0.174202 1.100623,-0.276315 0.990665,2.511077 l -0.05943,1.506494 -1.603304,0.949517 c -0.881814,0.522232 -1.724043,0.950374 -1.871618,0.951427 -0.14758,9.71e-4 -1.048256,-0.400375 -2.001513,-0.892061 z m 3.333494,-0.755504 c 1.144848,-0.665765 1.331783,-0.860718 1.306359,-1.362389 -0.01632,-0.321996 0.01604,-0.913691 0.0719,-1.314877 l 0.101567,-0.729431 -1.067859,0.187538 c -1.560943,0.27415 -4.375215,1.956236 -4.342809,2.595689 0.0075,0.147431 2.170163,1.330274 2.54565,1.392294 0.02704,0.0045 0.650377,-0.341504 1.385193,-0.768824 z"
+ id="path3254"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 33.395738,33.569979 c -2.232364,-2.202568 -2.115173,-1.863927 -1.315634,-3.801652 l 0.698139,-1.691981 2.04423,-0.535561 c 1.12433,-0.294555 2.095745,-0.486883 2.158701,-0.427393 0.24729,0.233676 0.237205,2.878699 -0.01516,3.975937 -0.24533,1.066639 -1.626457,3.398848 -2.134024,3.60357 -0.116392,0.04695 -0.762707,-0.458369 -1.436249,-1.12292 z m 1.984153,-0.92919 c 0.287356,-0.439024 0.630435,-1.176208 0.7624,-1.638185 0.257798,-0.902488 0.254377,-2.94289 -0.0049,-2.913888 -0.08655,0.0097 -0.71939,0.167937 -1.406333,0.351662 -1.230997,0.329252 -1.25714,0.352585 -1.815216,1.619992 l -0.566231,1.285929 1.098866,1.054215 c 0.604377,0.579819 1.168632,1.050679 1.253902,1.046358 0.08528,-0.0043 0.390144,-0.367058 0.677498,-0.806083 l 0,0 z"
+ id="path3258"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 28.010039,31.639351 -0.977166,-0.03197 -0.752837,-1.872064 c -0.414059,-1.029635 -0.685852,-1.940913 -0.603983,-2.025065 0.08188,-0.08415 0.805321,-0.552881 1.607672,-1.041621 l 1.45882,-0.888615 1.711554,1.045466 c 0.941355,0.575006 1.743903,1.076033 1.783442,1.113394 0.03954,0.03736 -0.273292,0.889952 -0.695172,1.894649 l -0.767055,1.826727 -0.894054,0.0055 c -0.49173,0.0031 -1.33378,-0.0088 -1.87122,-0.02643 l 0,0 z m 2.723286,-2.119574 0.52961,-1.176613 -1.213147,-0.754272 -1.213148,-0.754272 -1.034257,0.573198 c -0.568841,0.315259 -1.073035,0.647111 -1.12043,0.737454 -0.04739,0.09034 0.136963,0.700614 0.409684,1.356165 0.463617,1.114412 0.546778,1.195205 1.278993,1.242586 1.649372,0.106723 1.798348,0.02953 2.362695,-1.224246 l 0,0 z"
+ id="path3260"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 26.02598,39.851401 c -1.955781,-0.510159 -3.272669,-1.087708 -4.773489,-2.093517 -1.74231,-1.167648 -2.717022,-2.297506 -3.828406,-4.437779 -0.861794,-1.65962 -0.891822,-1.782335 -1.010854,-4.131114 -0.11985,-2.364904 -0.106108,-2.46045 0.596434,-4.146306 1.330682,-3.193186 4.346844,-5.871635 7.759787,-6.890937 1.901469,-0.567887 5.326564,-0.591577 7.222325,-0.04995 4.439499,1.268381 8.050915,4.948011 8.953889,9.12301 1.097373,5.073833 -2.532532,10.574536 -8.172023,12.383751 -1.711888,0.549193 -5.105056,0.67131 -6.747663,0.242833 z m 7.066042,-3.587832 c 0.608672,-0.245238 1.14589,-0.572164 1.193813,-0.726504 0.04792,-0.154339 0.206886,-0.239471 0.353246,-0.189179 0.32928,0.113144 1.983435,-2.300334 2.475188,-3.611394 0.273244,-0.728498 0.338975,-1.461611 0.266117,-2.968118 -0.08659,-1.793603 -0.169969,-2.135821 -0.804119,-3.306564 -1.0658,-1.96764 -3.079301,-3.653226 -5.01221,-4.195937 -0.833942,-0.234149 -1.63853,-0.376263 -1.787972,-0.315808 -0.149445,0.06045 -0.362368,0.602878 -0.473164,1.205383 l -0.201449,1.095465 0.04879,-1.37084 0.04879,-1.370841 -0.802693,0.158832 c -2.612789,0.516983 -4.855955,1.495542 -6.066029,2.646243 -0.713473,0.678468 -1.781704,2.609183 -2.022242,3.654988 -0.368839,1.603643 -0.215975,3.651861 0.379345,5.082863 0.542654,1.304396 2.229374,3.209435 3.480459,3.930949 1.820737,1.050035 2.611517,1.192136 5.297031,0.951859 1.614873,-0.144489 2.91801,-0.385704 3.627079,-0.671392 l 0,0 z"
+ id="path3021"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 16.312178,19.909323 c -1.358242,-1.008425 -0.784209,-2.260627 1.159264,-2.528833 1.132305,-0.15626 2.737529,0.317414 2.358858,0.69606 -0.511726,0.511689 -2.634477,2.357642 -2.713359,2.359548 -0.05074,0.0013 -0.412882,-0.235823 -0.804763,-0.526775 z"
+ id="path3024"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 31.45527,15.841735 c -0.644362,-0.12091 -2.42683,-0.165794 -3.961042,-0.09974 l -2.789479,0.120089 -0.04311,-0.850572 c -0.08736,-1.723704 1.455847,-2.959976 3.852333,-3.086138 1.475838,-0.0777 3.164474,0.472168 3.9216,1.276979 0.514717,0.547134 0.845329,1.567138 0.748264,2.308549 -0.08471,0.647048 -0.06424,0.64313 -1.72857,0.330833 z"
+ id="path3026"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 39.141528,19.743194 c -1.449922,-1.436277 -1.417448,-1.663553 0.250601,-1.753906 1.965873,-0.106536 3.261261,1.448254 2.093349,2.512465 -0.298385,0.271892 -0.657383,0.500168 -0.797772,0.507282 -0.140389,0.0071 -0.83617,-0.562513 -1.546178,-1.265841 z"
+ id="path3028"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 31.688221,25.642442 c -0.724869,-0.453179 -1.042516,-0.795853 -1.060143,-1.143661 -0.03953,-0.780018 0.152002,-1.884506 0.328346,-1.893443 0.713591,-0.03616 4.220505,2.877019 3.904203,3.243209 -0.05101,0.05905 -0.552799,0.182429 -1.115089,0.274161 -0.89706,0.146345 -1.149173,0.0875 -2.057317,-0.480266 z"
+ id="path3030"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 24.167422,25.244753 c -0.692761,-0.386758 -0.881389,-0.594614 -0.730863,-0.80536 0.335118,-0.469185 2.353061,-1.547711 3.274778,-1.750263 0.807272,-0.177407 0.863124,-0.156322 0.885276,0.334065 0.04676,1.035249 -0.176248,1.438885 -1.148523,2.07874 -0.543316,0.357552 -1.068638,0.653252 -1.167381,0.657108 -0.09874,0.0039 -0.599725,-0.227573 -1.113287,-0.51429 z"
+ id="path3032"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 22.144925,31.449991 c -0.757078,-1.604297 -0.777292,-3.726476 -0.03584,-3.762282 0.629543,-0.0305 1.77915,0.790072 2.097841,1.497239 0.715984,1.58875 0.715572,1.5919 -0.325546,2.477746 -0.534229,0.454554 -1.030566,0.831926 -1.102968,0.838603 -0.07241,0.0066 -0.357475,-0.46641 -0.63349,-1.051306 z"
+ id="path3034"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 26.319667,35.23841 -1.17722,-0.331436 1.055457,-0.914758 c 0.956353,-0.828865 1.159843,-0.914255 2.167167,-0.909411 0.611441,0.0029 1.412875,0.119149 1.780965,0.258241 0.707502,0.267348 1.785657,1.489442 1.552691,1.759984 -0.07566,0.08787 -1.052015,0.229283 -2.169695,0.314279 -1.481004,0.112633 -2.351421,0.06465 -3.209365,-0.176899 z"
+ id="path3036"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 28.227516,30.322749 c -0.269178,-0.102464 -1.182373,-1.585229 -1.20085,-1.949817 -0.0052,-0.101741 0.382743,-0.40981 0.861996,-0.684604 l 0.87137,-0.499623 1.021079,0.646407 1.021079,0.646405 -0.420858,0.892972 c -0.353761,0.7506 -0.53711,0.905713 -1.150002,0.972899 -0.401027,0.04395 -0.852746,0.03286 -1.003814,-0.02464 l 0,0 z"
+ id="path3040"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 33.648364,32.079092 -0.815466,-0.938617 0.357888,-0.981795 c 0.336194,-0.922283 0.429965,-1.002561 1.546969,-1.324384 0.653994,-0.188423 1.234591,-0.299584 1.290216,-0.247022 0.348167,0.328998 -0.913915,4.39748 -1.371329,4.420661 -0.106053,0.0054 -0.559771,-0.412605 -1.008278,-0.928843 z"
+ id="path3042"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 38.316125,40.063705 c -0.330351,-0.107162 -0.576035,-0.271438 -0.545967,-0.365063 0.03007,-0.09363 0.619749,-0.712153 1.310399,-1.3745 1.233854,-1.183289 1.265295,-1.198406 1.804633,-0.867686 0.564609,0.346217 0.924502,1.138187 0.759174,1.670618 -0.132946,0.428152 -1.41655,1.103055 -2.127192,1.118454 -0.330224,0.0072 -0.870698,-0.07467 -1.201047,-0.181823 z"
+ id="path3044"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 16.229544,39.234763 c -0.392339,-0.223048 -0.775236,-0.550984 -0.850883,-0.728745 -0.241905,-0.568439 0.03321,-1.317018 0.6372,-1.733757 0.58503,-0.403664 0.58862,-0.402667 1.350871,0.375017 1.8093,1.845929 1.880294,1.945271 1.559218,2.181792 -0.517553,0.38126 -1.947885,0.331234 -2.696406,-0.09431 z"
+ id="path3046"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="M 19.485,42.408748 C 16.930631,41.936367 14.884655,41.208894 12.872365,40.057542 2.3991749,34.065193 -0.57562983,20.429709 6.4587641,10.659792 7.4177273,9.3279092 9.1801874,7.5013192 10.446658,6.5267926 17.519118,1.0846589 27.359733,0.931272 34.610263,6.1501513 c 4.345124,3.1275891 7.24437,7.8896897 8.144789,13.3780657 0.286201,1.744506 0.198987,5.358034 -0.170201,7.051783 -0.333997,1.532304 -1.053201,3.608859 -1.68843,4.875 -1.379553,2.749731 -3.793426,5.617816 -6.165667,7.325842 -2.500958,1.800704 -5.721003,3.154637 -8.621423,3.62505 -1.668492,0.270611 -5.168305,0.27212 -6.624331,0.0028 l 0,6e-6 z m 4.23522,-7.562761 c 0.558793,-0.726233 0.5775,-0.735924 1.76478,-0.914346 0.66,-0.09918 1.604794,-0.325958 2.099544,-0.503943 l 0.899545,-0.323609 0.556731,0.556731 c 0.771519,0.771519 1.565844,1.139993 2.71026,1.257242 1.745225,0.178803 3.344949,-0.586571 4.029147,-1.92771 0.428928,-0.840771 0.347073,-2.245383 -0.176203,-3.023564 -0.317334,-0.471916 -1.36328,-1.318207 -1.8155,-1.468947 -0.07915,-0.02639 0.03033,-0.428578 0.243302,-0.893764 1.066953,-2.330531 1.02912,-5.611563 -0.09004,-7.808868 l -0.28512,-0.559791 0.556092,-0.23235 c 1.523905,-0.636727 2.214244,-1.669651 2.118702,-3.170121 -0.07696,-1.208622 -0.607013,-2.005253 -1.771461,-2.66238 -0.754025,-0.425514 -0.941142,-0.465474 -2.175,-0.464491 -1.532874,0.0012 -2.305952,0.299664 -3.1875,1.230518 -0.268125,0.283122 -0.486483,0.493085 -0.485241,0.466586 0.0012,-0.0265 0.09953,-0.31818 0.218415,-0.64818 0.878715,-2.439093 -0.674723,-5.0170198 -3.536837,-5.869373 -1.24093,-0.3695564 -3.399607,-0.2256947 -4.507946,0.3004252 -2.170022,1.0300902 -3.261936,3.2037278 -2.604179,5.1840488 0.14237,0.428634 0.218226,0.819961 0.16857,0.869616 -0.04965,0.04966 -0.09028,0.01173 -0.09028,-0.08429 0,-0.360723 -1.081357,-1.352281 -1.838754,-1.686058 -1.094979,-0.482547 -2.749179,-0.483755 -3.744348,-0.0027 -1.27208,0.614866 -2.069754,1.809139 -2.062767,3.088361 0.0056,1.029877 1.008547,2.375268 2.114483,2.83652 l 0.543614,0.226723 -0.498183,1.243379 c -0.887804,2.215807 -0.941409,4.777357 -0.145841,6.969122 0.202286,0.557292 0.354069,1.015733 0.337295,1.018757 -0.01678,0.003 -0.366118,0.174249 -0.776319,0.380499 -1.973326,0.992193 -2.4424056,3.241501 -1.007865,4.832863 0.807731,0.89603 1.804363,1.31387 3.13815,1.315671 1.337582,0.0018 2.161666,-0.297256 2.984141,-1.082961 l 0.618606,-0.590949 0.62207,0.317357 c 0.342138,0.174546 1.211265,0.472653 1.931394,0.662461 1.278688,0.337031 1.321609,0.363119 1.834324,1.114905 0.28875,0.423389 0.574599,0.772241 0.63522,0.775226 0.06062,0.003 0.364369,-0.324879 0.675,-0.728586 l 0,0 z"
+ id="path3197"
+ inkscape:connector-curvature="0"
+ transform="scale(1.2222222,1.2222222)" /><path
+ style="fill:#ffffff"
+ d="M 20.985,44.331546 C 19.03187,44.099317 17.9762,43.898953 16.685405,43.515487 8.4898669,41.080779 2.5713154,34.36467 1.1662149,25.905 0.89605547,24.278454 0.86691819,21.070206 1.1075048,19.440537 2.5415387,9.7267738 10.030326,2.2610758 19.813733,0.79198431 c 1.386672,-0.20822481 4.555862,-0.20822481 5.942534,0 C 31.071336,1.5901033 35.89261,4.2012202 39.305485,8.1300001 44.221066,13.788643 45.891357,21.47733 43.783909,28.745097 41.651107,36.100305 35.337696,42.055776 27.806325,43.816831 25.664956,44.317546 22.729909,44.539015 20.985,44.331546 l 0,0 z m 5.625,-1.919823 c 0.53625,-0.128337 1.1775,-0.273071 1.425,-0.321632 0.2475,-0.04856 0.534375,-0.157711 0.6375,-0.242559 0.103125,-0.08485 0.1875,-0.115245 0.1875,-0.06755 0,0.316989 3.436141,-1.286703 5.1,-2.380238 C 41.146387,34.67665 44.558592,25.861621 42.437361,17.49948 42.240541,16.723596 41.839614,15.50037 41.546412,14.7812 40.984866,13.403835 39.641112,11.055214 38.993479,10.319169 38.782566,10.079462 38.608333,9.8432122 38.606296,9.7941692 38.596965,9.5694805 36.377056,7.4143369 35.136063,6.425179 33.328635,4.9845344 30.322815,3.4953623 27.98436,2.882015 25.980291,2.3563728 22.660725,2.10969 20.76,2.34516 c -0.28875,0.035772 -0.8625,0.1067143 -1.275,0.1576505 -0.4125,0.050936 -0.98625,0.1603127 -1.275,0.2430587 -0.28875,0.082746 -0.890161,0.249978 -1.336471,0.3716265 -0.901352,0.2456775 -1.252776,0.3934596 -3.306454,1.3904368 -1.797702,0.872712 -3.345156,1.9799198 -4.9307474,3.5279639 -1.2396847,1.2103288 -2.7263275,3.0506606 -2.7263275,3.3749506 0,0.09303 -0.051494,0.169153 -0.1144308,0.169153 -0.062937,0 -0.1810619,0.122717 -0.2625,0.272705 -0.2684018,0.494326 -1.4917167,2.950729 -1.5076247,3.027295 -0.00857,0.04125 -0.1010041,0.2775 -0.205408,0.525 -0.1044039,0.2475 -0.201896,0.5175 -0.2166489,0.6 -0.014752,0.0825 -0.067613,0.2175 -0.1174661,0.3 -0.049853,0.0825 -0.1334688,0.3525 -0.1858122,0.6 -0.1357453,0.641858 -0.2112774,0.968997 -0.3809625,1.65 -0.6658136,2.672135 -0.3602218,7.842361 0.6028818,10.2 0.1011047,0.2475 0.2078886,0.585 0.2372978,0.75 0.084575,0.474507 1.6577554,3.572364 2.0015458,3.94138 0.170948,0.183491 0.2687628,0.33362 0.2173667,0.33362 -0.093543,0 0.64696,1.010472 1.1542057,1.575 0.1482575,0.165 0.4907333,0.564442 0.7610573,0.887649 0.3945054,0.471682 1.9846702,1.898635 2.741498,2.460115 0.0825,0.06121 0.38625,0.288743 0.675,0.505637 1.10524,0.830199 5.4,2.879709 5.4,2.576943 0,-0.05064 0.08437,-0.02605 0.1875,0.05464 0.237641,0.185952 1.348593,0.464385 2.8875,0.723681 1.541738,0.259775 5.470086,0.172319 6.825,-0.151942 z"
+ id="path3199"
+ inkscape:connector-curvature="0"
+ transform="scale(1.2222222,1.2222222)" /></svg> \ No newline at end of file
diff --git a/icons/embross.svg b/icons/embross.svg
index 2e15a5b..7d1fedd 100644
--- a/icons/embross.svg
+++ b/icons/embross.svg
@@ -1,109 +1,379 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16px"
- height="16px"
- id="svg3017"
- version="1.1"
- inkscape:version="0.48.0 r9654"
- sodipodi:docname="embross.svg">
- <defs
- id="defs3019" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="22.197802"
- inkscape:cx="8"
- inkscape:cy="10.328398"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
- inkscape:window-width="1366"
- inkscape:window-height="701"
- inkscape:window-x="0"
- inkscape:window-y="0"
- inkscape:window-maximized="1" />
- <metadata
- id="metadata3022">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="1.4415842"
- y="15.279208"
- id="text3025"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3027"
- x="1.4415842"
- y="15.279208"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;writing-mode:lr-tb;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="3.3336635"
- y="8.7019796"
- id="text3029"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3031" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="3.1985149"
- y="11.314851"
- id="text3033"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3035" /></text>
- <text
- xml:space="preserve"
- style="font-size:29.19195557px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="4.2054524"
- y="12.5575"
- id="text3056"
- sodipodi:linespacing="122%"
- transform="scale(1.0093569,0.99072982)"><tspan
- sodipodi:role="line"
- id="tspan3058"
- x="4.2054524"
- y="12.5575"
- style="font-size:13.1363802px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;writing-mode:lr-tb;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans">E</tspan></text>
- <path
- style="fill:#ffffff"
- d="m 5.540297,7.8204634 0,-4.6175743 2.4326733,0 2.4326737,0 0,0.4955446 0,0.4955445 -1.8470301,0 -1.8470298,0 0,1.4415842 0,1.4415842 1.734406,0 1.7344059,0 0,0.4955445 0,0.4955446 -1.7344059,0 -1.734406,0 0,1.6893564 0,1.6893569 1.8470298,0 1.8470301,0 0,0.495544 0,0.495545 -2.4326737,0 -2.4326733,0 0,-4.6175746 z"
- id="path3132"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#f5f5f5"
- d="m 5.540297,7.8204634 0,-4.6175743 2.4326733,0 2.4326737,0 0,0.4955446 0,0.4955445 -1.8470301,0 -1.8470298,0 0,1.4415842 0,1.4415842 1.734406,0 1.7344059,0 0,0.4955445 0,0.4955446 -1.7344059,0 -1.734406,0 0,1.6893564 0,1.6893569 1.8470298,0 1.8470301,0 0,0.495544 0,0.495545 -2.4326737,0 -2.4326733,0 0,-4.6175746 z"
- id="path3263"
- inkscape:connector-curvature="0" />
- </g>
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg width="22" height="17">
+ <circle cx="0" cy="0" r="1" fill="rgb(138,138,138)"/>
+ <circle cx="1" cy="0" r="1" fill="rgb(132,132,132)"/>
+ <circle cx="2" cy="0" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="3" cy="0" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="4" cy="0" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="5" cy="0" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="6" cy="0" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="7" cy="0" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="8" cy="0" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="9" cy="0" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="10" cy="0" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="11" cy="0" r="1" fill="rgb(133,132,132)"/>
+ <circle cx="12" cy="0" r="1" fill="rgb(137,143,145)"/>
+ <circle cx="13" cy="0" r="1" fill="rgb(136,140,145)"/>
+ <circle cx="14" cy="0" r="1" fill="rgb(132,131,130)"/>
+ <circle cx="15" cy="0" r="1" fill="rgb(133,134,134)"/>
+ <circle cx="16" cy="0" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="17" cy="0" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="18" cy="0" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="19" cy="0" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="20" cy="0" r="1" fill="rgb(132,132,132)"/>
+ <circle cx="21" cy="0" r="1" fill="rgb(138,138,138)"/>
+ <circle cx="0" cy="1" r="1" fill="rgb(132,132,132)"/>
+ <circle cx="1" cy="1" r="1" fill="rgb(126,126,126)"/>
+ <circle cx="2" cy="1" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="3" cy="1" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="4" cy="1" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="5" cy="1" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="6" cy="1" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="7" cy="1" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="8" cy="1" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="9" cy="1" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="10" cy="1" r="1" fill="rgb(127,128,129)"/>
+ <circle cx="11" cy="1" r="1" fill="rgb(128,129,129)"/>
+ <circle cx="12" cy="1" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="13" cy="1" r="1" fill="rgb(133,143,146)"/>
+ <circle cx="14" cy="1" r="1" fill="rgb(128,130,131)"/>
+ <circle cx="15" cy="1" r="1" fill="rgb(127,126,126)"/>
+ <circle cx="16" cy="1" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="17" cy="1" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="18" cy="1" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="19" cy="1" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="20" cy="1" r="1" fill="rgb(126,126,126)"/>
+ <circle cx="21" cy="1" r="1" fill="rgb(132,132,132)"/>
+ <circle cx="0" cy="2" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="1" cy="2" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="2" cy="2" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="3" cy="2" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="4" cy="2" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="5" cy="2" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="6" cy="2" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="7" cy="2" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="8" cy="2" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="9" cy="2" r="1" fill="rgb(128,130,130)"/>
+ <circle cx="10" cy="2" r="1" fill="rgb(129,129,130)"/>
+ <circle cx="11" cy="2" r="1" fill="rgb(128,129,129)"/>
+ <circle cx="12" cy="2" r="1" fill="rgb(128,127,126)"/>
+ <circle cx="13" cy="2" r="1" fill="rgb(129,132,131)"/>
+ <circle cx="14" cy="2" r="1" fill="rgb(135,145,150)"/>
+ <circle cx="15" cy="2" r="1" fill="rgb(128,127,128)"/>
+ <circle cx="16" cy="2" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="17" cy="2" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="18" cy="2" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="19" cy="2" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="20" cy="2" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="21" cy="2" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="0" cy="3" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="1" cy="3" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="2" cy="3" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="3" cy="3" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="4" cy="3" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="5" cy="3" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="6" cy="3" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="7" cy="3" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="8" cy="3" r="1" fill="rgb(129,129,130)"/>
+ <circle cx="9" cy="3" r="1" fill="rgb(128,129,128)"/>
+ <circle cx="10" cy="3" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="11" cy="3" r="1" fill="rgb(127,128,129)"/>
+ <circle cx="12" cy="3" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="13" cy="3" r="1" fill="rgb(127,125,125)"/>
+ <circle cx="14" cy="3" r="1" fill="rgb(131,137,137)"/>
+ <circle cx="15" cy="3" r="1" fill="rgb(133,142,147)"/>
+ <circle cx="16" cy="3" r="1" fill="rgb(127,126,125)"/>
+ <circle cx="17" cy="3" r="1" fill="rgb(128,129,129)"/>
+ <circle cx="18" cy="3" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="19" cy="3" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="20" cy="3" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="21" cy="3" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="0" cy="4" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="1" cy="4" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="2" cy="4" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="3" cy="4" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="4" cy="4" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="5" cy="4" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="6" cy="4" r="1" fill="rgb(128,128,127)"/>
+ <circle cx="7" cy="4" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="8" cy="4" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="9" cy="4" r="1" fill="rgb(128,128,127)"/>
+ <circle cx="10" cy="4" r="1" fill="rgb(128,129,129)"/>
+ <circle cx="11" cy="4" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="12" cy="4" r="1" fill="rgb(128,128,127)"/>
+ <circle cx="13" cy="4" r="1" fill="rgb(128,127,128)"/>
+ <circle cx="14" cy="4" r="1" fill="rgb(127,126,125)"/>
+ <circle cx="15" cy="4" r="1" fill="rgb(134,142,144)"/>
+ <circle cx="16" cy="4" r="1" fill="rgb(131,136,140)"/>
+ <circle cx="17" cy="4" r="1" fill="rgb(127,126,125)"/>
+ <circle cx="18" cy="4" r="1" fill="rgb(128,128,129)"/>
+ <circle cx="19" cy="4" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="20" cy="4" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="21" cy="4" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="0" cy="5" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="1" cy="5" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="2" cy="5" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="3" cy="5" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="4" cy="5" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="5" cy="5" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="6" cy="5" r="1" fill="rgb(126,126,124)"/>
+ <circle cx="7" cy="5" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="8" cy="5" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="9" cy="5" r="1" fill="rgb(128,128,129)"/>
+ <circle cx="10" cy="5" r="1" fill="rgb(127,128,128)"/>
+ <circle cx="11" cy="5" r="1" fill="rgb(128,127,128)"/>
+ <circle cx="12" cy="5" r="1" fill="rgb(128,127,128)"/>
+ <circle cx="13" cy="5" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="14" cy="5" r="1" fill="rgb(128,127,128)"/>
+ <circle cx="15" cy="5" r="1" fill="rgb(128,128,127)"/>
+ <circle cx="16" cy="5" r="1" fill="rgb(135,147,149)"/>
+ <circle cx="17" cy="5" r="1" fill="rgb(129,131,134)"/>
+ <circle cx="18" cy="5" r="1" fill="rgb(128,127,126)"/>
+ <circle cx="19" cy="5" r="1" fill="rgb(128,128,129)"/>
+ <circle cx="20" cy="5" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="21" cy="5" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="0" cy="6" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="1" cy="6" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="2" cy="6" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="3" cy="6" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="4" cy="6" r="1" fill="rgb(128,128,129)"/>
+ <circle cx="5" cy="6" r="1" fill="rgb(128,127,126)"/>
+ <circle cx="6" cy="6" r="1" fill="rgb(127,126,125)"/>
+ <circle cx="7" cy="6" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="8" cy="6" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="9" cy="6" r="1" fill="rgb(127,129,130)"/>
+ <circle cx="10" cy="6" r="1" fill="rgb(127,128,128)"/>
+ <circle cx="11" cy="6" r="1" fill="rgb(128,128,127)"/>
+ <circle cx="12" cy="6" r="1" fill="rgb(128,127,127)"/>
+ <circle cx="13" cy="6" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="14" cy="6" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="15" cy="6" r="1" fill="rgb(127,126,127)"/>
+ <circle cx="16" cy="6" r="1" fill="rgb(130,133,131)"/>
+ <circle cx="17" cy="6" r="1" fill="rgb(135,144,150)"/>
+ <circle cx="18" cy="6" r="1" fill="rgb(128,128,129)"/>
+ <circle cx="19" cy="6" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="20" cy="6" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="21" cy="6" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="0" cy="7" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="1" cy="7" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="2" cy="7" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="3" cy="7" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="4" cy="7" r="1" fill="rgb(127,128,127)"/>
+ <circle cx="5" cy="7" r="1" fill="rgb(127,125,124)"/>
+ <circle cx="6" cy="7" r="1" fill="rgb(128,128,129)"/>
+ <circle cx="7" cy="7" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="8" cy="7" r="1" fill="rgb(128,128,129)"/>
+ <circle cx="9" cy="7" r="1" fill="rgb(128,128,129)"/>
+ <circle cx="10" cy="7" r="1" fill="rgb(127,126,127)"/>
+ <circle cx="11" cy="7" r="1" fill="rgb(128,129,129)"/>
+ <circle cx="12" cy="7" r="1" fill="rgb(128,127,127)"/>
+ <circle cx="13" cy="7" r="1" fill="rgb(128,127,128)"/>
+ <circle cx="14" cy="7" r="1" fill="rgb(128,128,129)"/>
+ <circle cx="15" cy="7" r="1" fill="rgb(128,128,129)"/>
+ <circle cx="16" cy="7" r="1" fill="rgb(127,127,125)"/>
+ <circle cx="17" cy="7" r="1" fill="rgb(133,139,139)"/>
+ <circle cx="18" cy="7" r="1" fill="rgb(131,135,139)"/>
+ <circle cx="19" cy="7" r="1" fill="rgb(128,127,126)"/>
+ <circle cx="20" cy="7" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="21" cy="7" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="0" cy="8" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="1" cy="8" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="2" cy="8" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="3" cy="8" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="4" cy="8" r="1" fill="rgb(127,125,124)"/>
+ <circle cx="5" cy="8" r="1" fill="rgb(128,127,128)"/>
+ <circle cx="6" cy="8" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="7" cy="8" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="8" cy="8" r="1" fill="rgb(128,129,130)"/>
+ <circle cx="9" cy="8" r="1" fill="rgb(127,127,128)"/>
+ <circle cx="10" cy="8" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="11" cy="8" r="1" fill="rgb(127,126,127)"/>
+ <circle cx="12" cy="8" r="1" fill="rgb(128,127,128)"/>
+ <circle cx="13" cy="8" r="1" fill="rgb(128,127,128)"/>
+ <circle cx="14" cy="8" r="1" fill="rgb(128,127,129)"/>
+ <circle cx="15" cy="8" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="16" cy="8" r="1" fill="rgb(128,127,127)"/>
+ <circle cx="17" cy="8" r="1" fill="rgb(130,136,134)"/>
+ <circle cx="18" cy="8" r="1" fill="rgb(130,134,137)"/>
+ <circle cx="19" cy="8" r="1" fill="rgb(128,127,126)"/>
+ <circle cx="20" cy="8" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="21" cy="8" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="0" cy="9" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="1" cy="9" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="2" cy="9" r="1" fill="rgb(128,129,129)"/>
+ <circle cx="3" cy="9" r="1" fill="rgb(127,126,125)"/>
+ <circle cx="4" cy="9" r="1" fill="rgb(127,126,126)"/>
+ <circle cx="5" cy="9" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="6" cy="9" r="1" fill="rgb(128,128,127)"/>
+ <circle cx="7" cy="9" r="1" fill="rgb(128,128,127)"/>
+ <circle cx="8" cy="9" r="1" fill="rgb(130,130,129)"/>
+ <circle cx="9" cy="9" r="1" fill="rgb(130,131,131)"/>
+ <circle cx="10" cy="9" r="1" fill="rgb(127,127,128)"/>
+ <circle cx="11" cy="9" r="1" fill="rgb(128,127,126)"/>
+ <circle cx="12" cy="9" r="1" fill="rgb(127,127,128)"/>
+ <circle cx="13" cy="9" r="1" fill="rgb(128,127,128)"/>
+ <circle cx="14" cy="9" r="1" fill="rgb(128,127,128)"/>
+ <circle cx="15" cy="9" r="1" fill="rgb(128,127,128)"/>
+ <circle cx="16" cy="9" r="1" fill="rgb(127,126,126)"/>
+ <circle cx="17" cy="9" r="1" fill="rgb(131,136,135)"/>
+ <circle cx="18" cy="9" r="1" fill="rgb(130,134,136)"/>
+ <circle cx="19" cy="9" r="1" fill="rgb(128,127,126)"/>
+ <circle cx="20" cy="9" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="21" cy="9" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="0" cy="10" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="1" cy="10" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="2" cy="10" r="1" fill="rgb(129,129,128)"/>
+ <circle cx="3" cy="10" r="1" fill="rgb(128,125,125)"/>
+ <circle cx="4" cy="10" r="1" fill="rgb(127,127,128)"/>
+ <circle cx="5" cy="10" r="1" fill="rgb(128,129,129)"/>
+ <circle cx="6" cy="10" r="1" fill="rgb(129,128,127)"/>
+ <circle cx="7" cy="10" r="1" fill="rgb(130,130,128)"/>
+ <circle cx="8" cy="10" r="1" fill="rgb(129,129,130)"/>
+ <circle cx="9" cy="10" r="1" fill="rgb(131,131,129)"/>
+ <circle cx="10" cy="10" r="1" fill="rgb(133,134,132)"/>
+ <circle cx="11" cy="10" r="1" fill="rgb(128,127,128)"/>
+ <circle cx="12" cy="10" r="1" fill="rgb(128,127,127)"/>
+ <circle cx="13" cy="10" r="1" fill="rgb(128,127,128)"/>
+ <circle cx="14" cy="10" r="1" fill="rgb(128,127,128)"/>
+ <circle cx="15" cy="10" r="1" fill="rgb(129,128,128)"/>
+ <circle cx="16" cy="10" r="1" fill="rgb(127,126,126)"/>
+ <circle cx="17" cy="10" r="1" fill="rgb(131,136,135)"/>
+ <circle cx="18" cy="10" r="1" fill="rgb(130,134,136)"/>
+ <circle cx="19" cy="10" r="1" fill="rgb(128,127,127)"/>
+ <circle cx="20" cy="10" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="21" cy="10" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="0" cy="11" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="1" cy="11" r="1" fill="rgb(127,128,128)"/>
+ <circle cx="2" cy="11" r="1" fill="rgb(125,120,117)"/>
+ <circle cx="3" cy="11" r="1" fill="rgb(127,125,125)"/>
+ <circle cx="4" cy="11" r="1" fill="rgb(131,133,131)"/>
+ <circle cx="5" cy="11" r="1" fill="rgb(130,130,128)"/>
+ <circle cx="6" cy="11" r="1" fill="rgb(129,129,128)"/>
+ <circle cx="7" cy="11" r="1" fill="rgb(129,129,127)"/>
+ <circle cx="8" cy="11" r="1" fill="rgb(129,129,128)"/>
+ <circle cx="9" cy="11" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="10" cy="11" r="1" fill="rgb(131,130,128)"/>
+ <circle cx="11" cy="11" r="1" fill="rgb(133,135,130)"/>
+ <circle cx="12" cy="11" r="1" fill="rgb(129,128,127)"/>
+ <circle cx="13" cy="11" r="1" fill="rgb(127,127,128)"/>
+ <circle cx="14" cy="11" r="1" fill="rgb(127,128,127)"/>
+ <circle cx="15" cy="11" r="1" fill="rgb(128,127,129)"/>
+ <circle cx="16" cy="11" r="1" fill="rgb(128,125,126)"/>
+ <circle cx="17" cy="11" r="1" fill="rgb(131,135,136)"/>
+ <circle cx="18" cy="11" r="1" fill="rgb(130,133,136)"/>
+ <circle cx="19" cy="11" r="1" fill="rgb(128,127,127)"/>
+ <circle cx="20" cy="11" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="21" cy="11" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="0" cy="12" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="1" cy="12" r="1" fill="rgb(127,128,128)"/>
+ <circle cx="2" cy="12" r="1" fill="rgb(126,124,120)"/>
+ <circle cx="3" cy="12" r="1" fill="rgb(120,111,107)"/>
+ <circle cx="4" cy="12" r="1" fill="rgb(122,116,117)"/>
+ <circle cx="5" cy="12" r="1" fill="rgb(129,130,131)"/>
+ <circle cx="6" cy="12" r="1" fill="rgb(129,130,129)"/>
+ <circle cx="7" cy="12" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="8" cy="12" r="1" fill="rgb(128,128,129)"/>
+ <circle cx="9" cy="12" r="1" fill="rgb(129,128,129)"/>
+ <circle cx="10" cy="12" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="11" cy="12" r="1" fill="rgb(130,129,127)"/>
+ <circle cx="12" cy="12" r="1" fill="rgb(134,135,129)"/>
+ <circle cx="13" cy="12" r="1" fill="rgb(129,131,129)"/>
+ <circle cx="14" cy="12" r="1" fill="rgb(127,127,129)"/>
+ <circle cx="15" cy="12" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="16" cy="12" r="1" fill="rgb(127,126,126)"/>
+ <circle cx="17" cy="12" r="1" fill="rgb(131,135,137)"/>
+ <circle cx="18" cy="12" r="1" fill="rgb(130,132,135)"/>
+ <circle cx="19" cy="12" r="1" fill="rgb(128,127,127)"/>
+ <circle cx="20" cy="12" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="21" cy="12" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="0" cy="13" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="1" cy="13" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="2" cy="13" r="1" fill="rgb(129,129,130)"/>
+ <circle cx="3" cy="13" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="4" cy="13" r="1" fill="rgb(121,114,113)"/>
+ <circle cx="5" cy="13" r="1" fill="rgb(117,108,108)"/>
+ <circle cx="6" cy="13" r="1" fill="rgb(124,121,122)"/>
+ <circle cx="7" cy="13" r="1" fill="rgb(130,131,131)"/>
+ <circle cx="8" cy="13" r="1" fill="rgb(129,129,128)"/>
+ <circle cx="9" cy="13" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="10" cy="13" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="11" cy="13" r="1" fill="rgb(128,128,129)"/>
+ <circle cx="12" cy="13" r="1" fill="rgb(129,128,129)"/>
+ <circle cx="13" cy="13" r="1" fill="rgb(134,134,130)"/>
+ <circle cx="14" cy="13" r="1" fill="rgb(130,131,130)"/>
+ <circle cx="15" cy="13" r="1" fill="rgb(126,127,127)"/>
+ <circle cx="16" cy="13" r="1" fill="rgb(128,127,126)"/>
+ <circle cx="17" cy="13" r="1" fill="rgb(131,136,138)"/>
+ <circle cx="18" cy="13" r="1" fill="rgb(129,132,134)"/>
+ <circle cx="19" cy="13" r="1" fill="rgb(128,127,127)"/>
+ <circle cx="20" cy="13" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="21" cy="13" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="0" cy="14" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="1" cy="14" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="2" cy="14" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="3" cy="14" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="4" cy="14" r="1" fill="rgb(130,131,131)"/>
+ <circle cx="5" cy="14" r="1" fill="rgb(127,125,124)"/>
+ <circle cx="6" cy="14" r="1" fill="rgb(119,110,108)"/>
+ <circle cx="7" cy="14" r="1" fill="rgb(119,111,112)"/>
+ <circle cx="8" cy="14" r="1" fill="rgb(127,125,128)"/>
+ <circle cx="9" cy="14" r="1" fill="rgb(129,130,131)"/>
+ <circle cx="10" cy="14" r="1" fill="rgb(129,129,129)"/>
+ <circle cx="11" cy="14" r="1" fill="rgb(129,129,129)"/>
+ <circle cx="12" cy="14" r="1" fill="rgb(128,129,129)"/>
+ <circle cx="13" cy="14" r="1" fill="rgb(128,128,128)"/>
+ <circle cx="14" cy="14" r="1" fill="rgb(134,133,128)"/>
+ <circle cx="15" cy="14" r="1" fill="rgb(132,133,130)"/>
+ <circle cx="16" cy="14" r="1" fill="rgb(127,127,126)"/>
+ <circle cx="17" cy="14" r="1" fill="rgb(131,136,136)"/>
+ <circle cx="18" cy="14" r="1" fill="rgb(129,131,133)"/>
+ <circle cx="19" cy="14" r="1" fill="rgb(128,128,127)"/>
+ <circle cx="20" cy="14" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="21" cy="14" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="0" cy="15" r="1" fill="rgb(132,132,132)"/>
+ <circle cx="1" cy="15" r="1" fill="rgb(126,126,126)"/>
+ <circle cx="2" cy="15" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="3" cy="15" r="1" fill="rgb(127,127,127)"/>
+ <circle cx="4" cy="15" r="1" fill="rgb(127,126,126)"/>
+ <circle cx="5" cy="15" r="1" fill="rgb(127,128,128)"/>
+ <circle cx="6" cy="15" r="1" fill="rgb(129,130,129)"/>
+ <circle cx="7" cy="15" r="1" fill="rgb(123,119,117)"/>
+ <circle cx="8" cy="15" r="1" fill="rgb(116,108,105)"/>
+ <circle cx="9" cy="15" r="1" fill="rgb(120,115,116)"/>
+ <circle cx="10" cy="15" r="1" fill="rgb(124,122,125)"/>
+ <circle cx="11" cy="15" r="1" fill="rgb(125,124,125)"/>
+ <circle cx="12" cy="15" r="1" fill="rgb(126,125,126)"/>
+ <circle cx="13" cy="15" r="1" fill="rgb(127,126,126)"/>
+ <circle cx="14" cy="15" r="1" fill="rgb(126,126,126)"/>
+ <circle cx="15" cy="15" r="1" fill="rgb(130,130,128)"/>
+ <circle cx="16" cy="15" r="1" fill="rgb(132,132,129)"/>
+ <circle cx="17" cy="15" r="1" fill="rgb(131,136,139)"/>
+ <circle cx="18" cy="15" r="1" fill="rgb(128,129,131)"/>
+ <circle cx="19" cy="15" r="1" fill="rgb(127,127,126)"/>
+ <circle cx="20" cy="15" r="1" fill="rgb(126,126,126)"/>
+ <circle cx="21" cy="15" r="1" fill="rgb(132,132,132)"/>
+ <circle cx="0" cy="16" r="1" fill="rgb(138,138,138)"/>
+ <circle cx="1" cy="16" r="1" fill="rgb(132,132,132)"/>
+ <circle cx="2" cy="16" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="3" cy="16" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="4" cy="16" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="5" cy="16" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="6" cy="16" r="1" fill="rgb(133,132,132)"/>
+ <circle cx="7" cy="16" r="1" fill="rgb(134,135,136)"/>
+ <circle cx="8" cy="16" r="1" fill="rgb(133,133,133)"/>
+ <circle cx="9" cy="16" r="1" fill="rgb(127,122,118)"/>
+ <circle cx="10" cy="16" r="1" fill="rgb(126,120,117)"/>
+ <circle cx="11" cy="16" r="1" fill="rgb(125,119,119)"/>
+ <circle cx="12" cy="16" r="1" fill="rgb(124,118,118)"/>
+ <circle cx="13" cy="16" r="1" fill="rgb(125,118,117)"/>
+ <circle cx="14" cy="16" r="1" fill="rgb(124,119,117)"/>
+ <circle cx="15" cy="16" r="1" fill="rgb(124,118,118)"/>
+ <circle cx="16" cy="16" r="1" fill="rgb(127,119,116)"/>
+ <circle cx="17" cy="16" r="1" fill="rgb(134,133,130)"/>
+ <circle cx="18" cy="16" r="1" fill="rgb(134,135,136)"/>
+ <circle cx="19" cy="16" r="1" fill="rgb(133,133,132)"/>
+ <circle cx="20" cy="16" r="1" fill="rgb(132,132,132)"/>
+ <circle cx="21" cy="16" r="1" fill="rgb(138,138,138)"/>
</svg>
diff --git a/icons/finedges.svg b/icons/finedges.svg
index 3b16d4e..bdc4b34 100644
--- a/icons/finedges.svg
+++ b/icons/finedges.svg
@@ -9,92 +9,195 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16px"
- height="16px"
- id="svg3043"
- version="1.1"
+ version="1.0"
+ width="45"
+ height="45"
+ viewBox="0 0 55 55"
+ id="svg2"
+ xml:space="preserve"
inkscape:version="0.48.0 r9654"
- sodipodi:docname="finedges.svg">
- <defs
- id="defs3045" />
- <sodipodi:namedview
- id="base"
+ sodipodi:docname="finedges.svg"><metadata
+ id="metadata24"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
inkscape:pageshadow="2"
- inkscape:zoom="22.197802"
- inkscape:cx="7.7888027"
- inkscape:cy="6.9403464"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
inkscape:window-width="1366"
inkscape:window-height="701"
+ id="namedview22"
+ showgrid="false"
+ inkscape:zoom="6.6666667"
+ inkscape:cx="22.5"
+ inkscape:cy="17.57319"
inkscape:window-x="0"
inkscape:window-y="0"
- inkscape:window-maximized="1" />
- <metadata
- id="metadata3048">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="1.9821782"
- y="5.5485148"
- id="text3297"
- sodipodi:linespacing="125%"><tspan
- sodipodi:role="line"
- id="tspan3299" /></text>
- <text
- xml:space="preserve"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="13.740099"
- y="14.423267"
- id="text3305"
- sodipodi:linespacing="125%"><tspan
- sodipodi:role="line"
- id="tspan3307" /></text>
- <text
- xml:space="preserve"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="0.67574257"
- y="14.918812"
- id="text3309"
- sodipodi:linespacing="125%"><tspan
- sodipodi:role="line"
- id="tspan3311" /></text>
- <text
- xml:space="preserve"
- style="font-size:13.50702095px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="5.1331983"
- y="13.114629"
- id="text3313"
- sodipodi:linespacing="125%"
- transform="scale(1.020869,0.9795576)"><tspan
- sodipodi:role="line"
- id="tspan3315"
- x="5.1331983"
- y="13.114629">f</tspan></text>
- <path
- style="fill:#f5f5f5"
- d="m 6.7706839,9.7444061 0,-3.1084159 -0.6555721,0 -0.6555721,0 L 5.4731563,6.4030397 5.486773,6.1700893 6.1174661,5.9601549 6.7481591,5.7502206 6.7771927,5.0330807 C 6.8193983,3.9905895 7.0046848,3.4968714 7.4878301,3.1395026 7.8393087,2.8795238 8.2268772,2.7842575 8.9330601,2.7842575 c 0.5975615,0 1.2211019,0.1010956 1.2876469,0.2087682 0.02506,0.040551 -0.190196,0.7516978 -0.2465672,0.8145826 C 9.9582342,3.8253522 9.8239135,3.8069587 9.67565,3.7667341 9.3244588,3.6714539 8.6934965,3.6694407 8.4772412,3.7629104 8.2831961,3.8467805 8.1059794,4.067469 8.0331486,4.3159407 c -0.02905,0.099109 -0.064245,0.469078 -0.07821,0.8221535 l -0.025391,0.6419554 0.8396274,0 0.8396273,0 0,0.4279703 0,0.4279703 -0.8334158,0 -0.8334159,0 0,3.1084159 0,3.1084159 -0.5856436,0 -0.5856435,0 0,-3.1084159 z"
- id="path3323"
- inkscape:connector-curvature="0" />
- </g>
-</svg>
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" /><defs
+ id="defs12">
+
+</defs><path
+ d=""
+ id="path2385"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:1.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><g
+ transform="matrix(1.3571325,0.10790977,-0.07757718,1.0961287,-6.6637309,-5.6395051)"
+ id="g2937"><path
+ d="m 27.567493,45.252146 c -0.46948,0 -0.933016,-0.02903 -1.389761,-0.08296 l 1.178368,1.948634 1.161389,-1.918769 c -0.314968,0.02489 -0.629086,0.05309 -0.949996,0.05309 z"
+ id="path3003"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 38.317981,14.929279 c -1.837168,0 -3.360217,1.289964 -3.68707,2.992219 1.578232,1.115757 2.934884,2.584076 3.968928,4.320343 1.939893,-0.142684 3.475677,-1.709721 3.475677,-3.641764 0,-2.027442 -1.682656,-3.670798 -3.757535,-3.670798 z"
+ id="path3007"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 38.787461,38.290488 c -1.039138,1.851575 -2.42805,3.426908 -4.072502,4.609029 0.442312,1.546298 1.878767,2.686942 3.603022,2.686942 2.07403,0 3.757535,-1.642527 3.757535,-3.669969 0,-1.870656 -1.437304,-3.397874 -3.288055,-3.626002 z"
+ id="path3009"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 16.340734,38.277215 c -1.912727,0.170889 -3.41625,1.724653 -3.41625,3.639275 0,2.026612 1.680958,3.669969 3.755837,3.669969 1.752271,0 3.212497,-1.177974 3.626793,-2.764091 -1.598607,-1.174655 -2.950165,-2.728419 -3.96638,-4.545153 z"
+ id="path3011"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 20.375881,18.007772 c -0.291196,-1.744563 -1.828678,-3.078493 -3.69556,-3.078493 -2.074879,0 -3.755837,1.643356 -3.755837,3.669968 0,1.97601 1.601155,3.575399 3.603872,3.655037 1.006876,-1.694789 2.319381,-3.139051 3.847525,-4.246512 z"
+ id="path3013"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 27.567493,15.62362 c 1.619832,0 3.164955,0.340948 4.599711,0.935742 0.629086,-0.892605 1.000085,-1.971862 1.000085,-3.138221 0,-3.058584 -2.537567,-5.5389654 -5.668563,-5.5389654 -3.130146,0 -5.667713,2.4803814 -5.667713,5.5389654 0,1.18461 0.383734,2.280457 1.032345,3.180529 1.463622,-0.62134 3.04525,-0.97805 4.704135,-0.97805 z"
+ id="path3015"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3017"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z"
+ id="path3019"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /></g><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3021"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z"
+ id="path3023"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z"
+ id="path3025"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z"
+ id="path3027"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z"
+ id="path3029"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z"
+ id="path3031"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z"
+ id="path3033"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /></g></g><path
+ style="fill:#000000"
+ d="M 25.313598,45.74729 C 21.440834,44.96393 17.279164,42.641313 15.032579,40.009483 13.592476,38.322434 12.236387,35.683559 11.682336,33.4901 9.360623,24.29853 17.429111,15.327866 28.018005,15.327866 c 8.496715,0 16.150436,6.130107 17.332356,13.882033 1.343718,8.813085 -6.690983,16.947491 -16.615487,16.821677 -1.182833,-0.01498 -2.722408,-0.142916 -3.421276,-0.284286 z m 8.511046,-4.997786 c 0.985694,-0.356641 1.792173,-0.746087 1.792173,-0.865438 0,-0.119361 -0.322591,-0.529506 -0.71687,-0.911459 -0.394277,-0.381954 -0.716869,-0.830428 -0.716869,-0.99661 0,-0.166177 0.45541,0.153009 1.012022,0.709321 l 1.012022,1.011474 1.14283,-1.323076 c 0.628556,-0.727693 1.495672,-1.988375 1.92692,-2.801516 0.706432,-1.332012 0.784091,-1.77129 0.784091,-4.435315 0,-2.627496 -0.0845,-3.121566 -0.75847,-4.435316 -1.021381,-1.990917 -2.840588,-4.067147 -4.377409,-4.995866 -1.246636,-0.753353 -4.444047,-1.782144 -4.704401,-1.513674 -0.07367,0.07597 -0.366944,1.372104 -0.651723,2.880302 l -0.517778,2.742177 0.166965,-3.05162 0.166963,-3.051618 -0.970299,0.155669 c -0.533666,0.0856 -1.613511,0.240877 -2.399657,0.345034 -2.825982,0.374413 -6.26404,2.458478 -7.227438,4.381093 -0.255137,0.50917 -0.634175,1.058825 -0.8423,1.221451 -0.643654,0.502945 -1.334923,3.960105 -1.182741,5.915099 0.337478,4.335314 3.953806,8.413866 8.525963,9.615715 1.750964,0.460263 6.541314,0.125889 8.536006,-0.595817 l 0,0 z"
+ id="path3216"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="M 11.099897,44.175965 C 8.9281401,43.187441 8.6175585,41.312091 10.458518,40.303201 l 1.079107,-0.591375 1.834447,2.069812 1.834449,2.069814 -0.762948,0.356272 c -0.999234,0.466612 -2.275402,0.454491 -3.343676,-0.03176 z"
+ id="path3218"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="m 12.50545,18.302096 c -1.863779,-1.171861 -1.98494,-2.52471 -0.322551,-3.601505 1.143202,-0.740501 3.388217,-0.65387 4.619174,0.17824 l 0.827468,0.559358 -0.671335,0.457155 c -0.369233,0.25144 -1.334942,1.01353 -2.146017,1.693538 l -1.474684,1.236376 -0.832055,-0.523162 0,0 z"
+ id="path3220"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="m 33.609583,13.614804 c -0.905681,-0.323971 -2.572641,-0.480296 -5.591578,-0.524369 l -4.301214,-0.06279 -0.08625,-1.179989 c -0.17245,-2.3592973 2.313624,-4.2020449 5.677833,-4.2085518 4.084678,-0.00789 7.138521,2.8662978 6.194857,5.8304468 -0.242404,0.761413 -0.183711,0.756908 -1.893643,0.145261 z"
+ id="path3222"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="m 42.948256,19.269531 c -1.915819,-2.131377 -1.886231,-2.445805 0.253537,-2.694509 3.415255,-0.396951 5.665594,2.830556 2.912767,4.177586 -0.538105,0.263307 -1.087909,0.463147 -1.221783,0.444088 -0.133872,-0.01912 -1.008912,-0.886283 -1.944521,-1.927165 z"
+ id="path3224"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="m 32.530294,26.645316 -1.509409,-1.126496 0.17656,-1.478438 c 0.09711,-0.813141 0.260193,-1.57092 0.362418,-1.683956 0.366212,-0.404936 3.078904,1.282427 4.415392,2.746486 0.749127,0.820636 1.362052,1.601604 1.362052,1.735491 0,0.323447 -0.527738,0.515731 -2.042261,0.74411 -1.138996,0.171756 -1.395229,0.0849 -2.764748,-0.937197 l 0,0 z"
+ id="path3226"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="m 22.567917,25.746376 c -1.814224,-0.941662 -1.754281,-0.864032 -1.175977,-1.522974 0.658625,-0.750462 3.467093,-2.026296 5.026463,-2.283421 1.226145,-0.202181 1.254439,-0.188945 1.074928,0.502844 -0.101392,0.390774 -0.186119,1.074492 -0.188277,1.51938 -0.0032,0.686747 -0.253158,0.938624 -1.6546,1.668126 l -1.650682,0.85924 -1.431854,-0.743195 0,0 z"
+ id="path3228"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="m 19.076248,33.762719 c -0.613645,-1.382172 -0.712303,-1.950697 -0.586588,-3.380328 0.08312,-0.945282 0.233862,-1.856724 0.334975,-2.025427 0.116593,-0.194543 0.753768,-0.01853 1.742067,0.481323 1.450022,0.733326 1.59709,0.906705 2.117788,2.496654 l 0.559559,1.708601 -1.449885,1.190407 c -0.797437,0.654723 -1.569202,1.190406 -1.715039,1.190406 -0.14584,0 -0.597129,-0.747736 -1.002877,-1.661636 z"
+ id="path3230"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="m 27.916051,32.798164 c -0.836258,-0.158902 -1.033271,-0.376351 -1.505192,-1.661279 -0.298647,-0.813141 -0.543098,-1.488959 -0.543228,-1.501815 -1.28e-4,-0.01281 0.626308,-0.325984 1.392081,-0.695837 l 1.392317,-0.672456 1.418137,0.967671 1.418136,0.967673 -0.731531,1.425879 c -0.766611,1.49425 -0.882974,1.542185 -2.84072,1.170164 l 0,0 z"
+ id="path3232"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d=""
+ id="path3234"
+ inkscape:connector-curvature="0"
+ transform="scale(1.2222222,1.2222222)" /><path
+ style="fill:#000000"
+ d="m 34.803914,35.482659 -1.153055,-1.420131 0.566214,-1.304112 c 0.31142,-0.717262 0.617757,-1.35726 0.680757,-1.422222 0.06299,-0.06495 0.895722,-0.286212 1.8505,-0.491668 l 1.735961,-0.373553 -0.0028,1.220019 c -0.0033,1.510036 -1.685152,5.211801 -2.36771,5.211801 -0.08622,0 -0.675622,-0.63906 -1.309801,-1.420134 z"
+ id="path3236"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="m 24.911198,39.295643 c -0.920187,-0.313619 -1.736538,-0.635662 -1.81411,-0.715655 -0.07757,-0.07999 0.56656,-0.69634 1.431407,-1.369664 l 1.572449,-1.224225 2.164717,0.202277 c 2.147364,0.200656 2.173957,0.213578 3.31755,1.612093 1.396577,1.707896 1.310876,1.776915 -2.418217,1.947403 -2.010672,0.09192 -2.950289,-0.0078 -4.253796,-0.452229 z"
+ id="path3238"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d="m 40.79981,46.583117 c -1.316889,-0.490997 -1.382178,-0.920585 -0.249948,-1.644628 0.519903,-0.33247 1.385241,-1.073958 1.922972,-1.647749 0.974932,-1.04031 0.980061,-1.041824 1.817556,-0.536959 1.042021,0.628163 1.461149,1.391709 1.246968,2.27168 -0.344874,1.41693 -2.87969,2.250352 -4.737548,1.557656 l 0,0 z"
+ id="path3240"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#000000"
+ d=""
+ id="path3242"
+ inkscape:connector-curvature="0"
+ transform="scale(1.2222222,1.2222222)" /><path
+ style="fill:#000000"
+ d=""
+ id="path3244"
+ inkscape:connector-curvature="0"
+ transform="scale(1.2222222,1.2222222)" /><path
+ style="fill:#ffffff"
+ d="m 24.554887,40.753837 c -1.766799,-0.596728 -3.596672,-1.685292 -3.73982,-2.22476 -0.04314,-0.16263 1.016367,-1.14405 2.354484,-2.180936 l 2.432941,-1.885245 2.354747,0.200708 c 1.295111,0.110392 2.577583,0.268178 2.849935,0.350644 0.472272,0.142994 4.236147,4.446105 4.236147,4.843039 0,0.47496 -3.521454,1.281299 -6.021699,1.378839 -2.150601,0.08389 -3.090978,-0.01754 -4.466735,-0.482289 z m 7.03335,-0.918671 c 0.796317,-0.176103 1.44785,-0.428567 1.44785,-0.561031 0,-0.132469 -0.541848,-0.903647 -1.204108,-1.713741 l -1.204106,-1.472896 -2.382355,-0.199329 -2.382354,-0.199332 -1.754638,1.39226 -1.754641,1.39226 0.824826,0.454529 c 2.098866,1.156599 5.582601,1.532449 8.409526,0.90728 z"
+ id="path3246"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="M 34.452294,37.274723 C 31.570029,34.171194 31.705979,34.633004 32.92608,32.090346 l 1.065367,-2.220197 2.815169,-0.57892 c 1.548342,-0.318405 2.881826,-0.510185 2.963291,-0.426179 0.319994,0.329969 0.12411,3.874179 -0.294455,5.327567 -0.40689,1.41286 -2.44459,4.444709 -3.148518,4.684607 -0.161418,0.05502 -1.005012,-0.666114 -1.87464,-1.602501 z m 2.76063,-1.110548 c 0.420779,-0.568869 0.937828,-1.53355 1.148997,-2.143736 0.412592,-1.192205 0.5483,-3.925183 0.194057,-3.908075 -0.460946,0.02225 -3.834157,0.816069 -3.897894,0.917277 -0.03714,0.05898 -0.376554,0.809603 -0.754241,1.66804 l -0.686704,1.5608 1.404119,1.469998 c 0.772269,0.808502 1.499184,1.470002 1.615368,1.470002 0.116198,0 0.555521,-0.465437 0.976298,-1.034306 l 0,0 z"
+ id="path3248"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 27.260782,34.321269 -1.330713,-0.109422 -0.87414,-2.572384 c -0.480776,-1.414812 -0.785208,-2.654489 -0.676518,-2.754838 0.108698,-0.100354 1.123098,-0.67689 2.254231,-1.281207 l 2.056609,-1.098757 2.244604,1.547439 c 1.234534,0.851093 2.285019,1.580192 2.334412,1.620222 0.0494,0.04004 -0.435934,1.151023 -1.078504,2.468878 l -1.168309,2.396094 -1.215478,-0.05329 c -0.66851,-0.02931 -1.814299,-0.102537 -2.546194,-0.162727 l 0,0 z m 3.846562,-2.588729 0.771451,-1.622004 -1.496445,-1.039184 c -0.823046,-0.571553 -1.668748,-1.039187 -1.879335,-1.039187 -0.210589,0 -0.958322,0.34774 -1.661627,0.772756 -1.37327,0.829881 -1.345633,0.674797 -0.547292,3.071183 0.295954,0.888369 0.503315,1.060366 1.464462,1.214711 2.49744,0.401054 2.515501,0.393729 3.348786,-1.358275 l 0,0 z"
+ id="path3250"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 31.673079,27.799683 c -2.322841,-1.804674 -2.289651,-1.702055 -1.694051,-5.237738 0.346028,-2.054145 0.35512,-2.069057 1.201056,-1.96988 2.685017,0.314791 6.207368,3.15009 7.708601,6.204998 l 0.739393,1.504611 -1.073702,0.198765 c -0.590534,0.109323 -1.912869,0.359618 -2.938518,0.556216 l -1.864817,0.357451 -2.077962,-1.614423 0,0 z m 5.715464,-0.320573 c 0.495339,-0.188945 0.474596,-0.29572 -0.303095,-1.560246 -0.968488,-1.574757 -2.228042,-2.639056 -4.173329,-3.526374 -1.436259,-0.655136 -1.862817,-0.516204 -1.882029,0.612986 -0.0042,0.243942 -0.08482,0.9253 -0.179275,1.514128 -0.163388,1.018596 -0.09709,1.130403 1.365206,2.301828 1.483078,1.188093 1.591305,1.22474 3.088858,1.045871 0.853562,-0.101954 1.791206,-0.276635 2.083657,-0.388193 z"
+ id="path3252"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 21.136062,26.685012 c -1.26387,-0.724961 -2.252803,-1.481404 -2.202281,-1.684546 0.153028,-0.61533 1.839949,-2.275449 3.063552,-3.014885 1.33787,-0.80849 3.71452,-1.533951 5.662237,-1.728376 1.562588,-0.155984 1.51487,-0.295565 1.173445,3.432664 l -0.184532,2.014985 -2.244425,1.163657 c -1.234427,0.64001 -2.408574,1.156606 -2.609214,1.147993 -0.20064,-0.0087 -1.397091,-0.607785 -2.658782,-1.331492 z m 4.582533,-0.786125 c 1.601799,-0.814509 1.869288,-1.063092 1.869288,-1.737165 0,-0.432649 0.08472,-1.223448 0.188279,-1.75733 l 0.188279,-0.970693 -1.464226,0.178811 c -2.140335,0.261403 -6.081022,2.324608 -6.081022,3.183812 0,0.198096 2.857809,1.930246 3.363856,2.03887 0.03644,0.0078 0.907438,-0.413515 1.935546,-0.936305 z"
+ id="path3254"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d=""
+ id="path3256"
+ inkscape:connector-curvature="0"
+ transform="scale(1.2222222,1.2222222)" /><path
+ style="fill:#ffffff"
+ d="M 34.452294,37.274723 C 31.570029,34.171194 31.705979,34.633004 32.92608,32.090346 l 1.065367,-2.220197 2.815169,-0.57892 c 1.548342,-0.318405 2.881826,-0.510185 2.963291,-0.426179 0.319994,0.329969 0.12411,3.874179 -0.294455,5.327567 -0.40689,1.41286 -2.44459,4.444709 -3.148518,4.684607 -0.161418,0.05502 -1.005012,-0.666114 -1.87464,-1.602501 z m 2.76063,-1.110548 c 0.420779,-0.568869 0.937828,-1.53355 1.148997,-2.143736 0.412526,-1.192014 0.548413,-3.926817 0.194057,-3.905559 -0.118286,0.0071 -0.989277,0.17621 -1.935546,0.375785 -1.695705,0.357658 -1.732843,0.387152 -2.57861,2.047845 l -0.858124,1.684959 1.42084,1.487506 c 0.781464,0.818128 1.515904,1.487506 1.632088,1.487506 0.116198,0 0.555521,-0.465437 0.976298,-1.034306 l 0,0 z"
+ id="path3258"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ d="m 27.265653,34.321476 -1.325847,-0.109238 -0.894229,-2.560094 c -0.491824,-1.408054 -0.798449,-2.64782 -0.681384,-2.755041 0.117063,-0.107223 1.132579,-0.686282 2.256703,-1.286799 l 2.043861,-1.091852 2.254139,1.517396 c 1.239777,0.834567 2.295998,1.560559 2.347159,1.613315 0.05115,0.05275 -0.432722,1.174162 -1.075292,2.492016 l -1.168309,2.396101 -1.215478,-0.05329 c -0.66851,-0.02931 -1.812108,-0.102453 -2.541323,-0.162511 l 0,0 z m 3.847162,-2.655714 0.800826,-1.54094 -1.596817,-1.09328 -1.596819,-1.093285 -1.445123,0.697963 c -0.794814,0.383879 -1.502915,0.794388 -1.573551,0.912244 -0.07064,0.117862 0.137885,0.948276 0.463388,1.845378 0.55334,1.525036 0.660797,1.638965 1.652674,1.752195 2.234284,0.255059 2.442072,0.161721 3.295422,-1.480275 l 0,0 z"
+ id="path3260"
+ inkscape:connector-curvature="0" /></svg> \ No newline at end of file
diff --git a/icons/grey.svg b/icons/grey.svg
index 4eb8472..f5a9a30 100644
--- a/icons/grey.svg
+++ b/icons/grey.svg
@@ -9,86 +9,108 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16px"
- height="16px"
- id="svg3017"
- version="1.1"
+ version="1.0"
+ width="45"
+ height="45"
+ viewBox="0 0 55 55"
+ id="svg2"
+ xml:space="preserve"
inkscape:version="0.48.0 r9654"
- sodipodi:docname="grey.svg">
- <defs
- id="defs3019" />
- <sodipodi:namedview
- id="base"
+ sodipodi:docname="grey.svg"><metadata
+ id="metadata24"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
inkscape:pageshadow="2"
- inkscape:zoom="22.197802"
- inkscape:cx="8"
- inkscape:cy="7.3052196"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
inkscape:window-width="1366"
inkscape:window-height="701"
+ id="namedview22"
+ showgrid="false"
+ inkscape:zoom="6.6666667"
+ inkscape:cx="22.5"
+ inkscape:cy="22.5"
inkscape:window-x="0"
inkscape:window-y="0"
- inkscape:window-maximized="1" />
- <metadata
- id="metadata3022">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="1.4415842"
- y="15.279208"
- id="text3025"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3027"
- x="1.4415842"
- y="15.279208"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;writing-mode:lr-tb;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="3.3336635"
- y="8.7019796"
- id="text3029"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3031" /></text>
- <text
- xml:space="preserve"
- style="font-size:12.65840054px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="3.8965118"
- y="12.109899"
- id="text3041"
- sodipodi:linespacing="125%"
- transform="scale(0.94927888,1.0534312)"><tspan
- sodipodi:role="line"
- id="tspan3043"
- x="3.8965118"
- y="12.109899">G</tspan></text>
- <path
- style="fill:#f5f5f5"
- d="M 7.4098515,12.781578 C 6.1820894,12.510841 5.2609612,11.653394 4.8229633,10.373532 4.5453404,9.5622969 4.435353,8.717675 4.4735346,7.6901764 4.5320841,6.1145624 4.9267076,5.068623 5.7829135,4.2197023 6.1119391,3.8934762 6.2766621,3.7698051 6.6120263,3.5972193 7.5754672,3.1014111 8.8077893,2.9942705 9.9888834,3.3036283 c 0.2783056,0.072895 0.8845426,0.3118392 0.9452786,0.3725745 0.01519,0.01519 -0.338535,0.9325931 -0.373093,0.9676356 -0.0092,0.00937 -0.177992,-0.047951 -0.375012,-0.1273704 C 9.6386942,4.295826 9.2135229,4.1968248 8.6893829,4.1679674 7.8180297,4.1199937 7.1210605,4.3647728 6.5786146,4.90928 5.8890943,5.6014204 5.5849223,6.5575251 5.58642,8.0280477 c 0.00111,1.0872752 0.1066919,1.6528565 0.4372757,2.3423423 0.5995403,1.25044 1.8553742,1.724536 3.632985,1.371507 l 0.3885673,-0.07717 0,-1.43542 0,-1.4354187 -0.8784658,0 -0.8784654,0 0,-0.5180693 0,-0.5180693 1.4190595,0 1.4190597,0 0,2.3129493 0,2.312948 -0.394184,0.117907 c -0.562028,0.168112 -0.696364,0.198258 -1.2333802,0.27678 -0.5813391,0.085 -1.7103017,0.08676 -2.0890203,0.0032 l 0,-1e-6 z"
- id="path3045"
- inkscape:connector-curvature="0" />
- </g>
-</svg>
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" /><defs
+ id="defs12">
+
+</defs><path
+ d=""
+ id="path2385"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:1.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path
+ sodipodi:type="arc"
+ style="fill:#c0c0c0"
+ id="path3303"
+ sodipodi:cx="60.375"
+ sodipodi:cy="20.174999"
+ sodipodi:rx="12.825"
+ sodipodi:ry="14.325"
+ d="m 73.2,20.174999 a 12.825,14.325 0 1 1 -25.65,0 12.825,14.325 0 1 1 25.65,0 z"
+ transform="matrix(1.6939571,0,0,1.6061664,-74.497661,-5.3627398)" /><g
+ transform="matrix(1.0772616,0.0871964,-0.06307273,0.97342202,-0.08355941,-3.8955918)"
+ id="g2937-8"><path
+ d="m 27.567493,45.252146 c -0.46948,0 -0.933016,-0.02903 -1.389761,-0.08296 l 1.178368,1.948634 1.161389,-1.918769 c -0.314968,0.02489 -0.629086,0.05309 -0.949996,0.05309 z"
+ id="path3003-9"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 38.317981,14.929279 c -1.837168,0 -3.360217,1.289964 -3.68707,2.992219 1.578232,1.115757 2.934884,2.584076 3.968928,4.320343 1.939893,-0.142684 3.475677,-1.709721 3.475677,-3.641764 0,-2.027442 -1.682656,-3.670798 -3.757535,-3.670798 z"
+ id="path3007-2"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 38.787461,38.290488 c -1.039138,1.851575 -2.42805,3.426908 -4.072502,4.609029 0.442312,1.546298 1.878767,2.686942 3.603022,2.686942 2.07403,0 3.757535,-1.642527 3.757535,-3.669969 0,-1.870656 -1.437304,-3.397874 -3.288055,-3.626002 z"
+ id="path3009-6"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 16.340734,38.277215 c -1.912727,0.170889 -3.41625,1.724653 -3.41625,3.639275 0,2.026612 1.680958,3.669969 3.755837,3.669969 1.752271,0 3.212497,-1.177974 3.626793,-2.764091 -1.598607,-1.174655 -2.950165,-2.728419 -3.96638,-4.545153 z"
+ id="path3011-6"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 20.375881,18.007772 c -0.291196,-1.744563 -1.828678,-3.078493 -3.69556,-3.078493 -2.074879,0 -3.755837,1.643356 -3.755837,3.669968 0,1.97601 1.601155,3.575399 3.603872,3.655037 1.006876,-1.694789 2.319381,-3.139051 3.847525,-4.246512 z"
+ id="path3013-4"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 27.567493,15.62362 c 1.619832,0 3.164955,0.340948 4.599711,0.935742 0.629086,-0.892605 1.000085,-1.971862 1.000085,-3.138221 0,-3.058584 -2.537567,-5.5389654 -5.668563,-5.5389654 -3.130146,0 -5.667713,2.4803814 -5.667713,5.5389654 0,1.18461 0.383734,2.280457 1.032345,3.180529 1.463622,-0.62134 3.04525,-0.97805 4.704135,-0.97805 z"
+ id="path3015-9"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3017-5"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z"
+ id="path3019-0"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /></g><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3021-4"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z"
+ id="path3023-8"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z"
+ id="path3025-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z"
+ id="path3027-1"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z"
+ id="path3029-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z"
+ id="path3031-2"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z"
+ id="path3033-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /></g></g></svg> \ No newline at end of file
diff --git a/icons/invert.svg b/icons/invert.svg
index f4bb71a..a9667b9 100644
--- a/icons/invert.svg
+++ b/icons/invert.svg
@@ -1,104 +1,379 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16px"
- height="16px"
- id="svg3017"
- version="1.1"
- inkscape:version="0.48.0 r9654"
- sodipodi:docname="invert.svg">
- <defs
- id="defs3019" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="22.197802"
- inkscape:cx="8"
- inkscape:cy="10.328398"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
- inkscape:window-width="1366"
- inkscape:window-height="701"
- inkscape:window-x="0"
- inkscape:window-y="0"
- inkscape:window-maximized="1" />
- <metadata
- id="metadata3022">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="1.4415842"
- y="15.279208"
- id="text3025"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3027"
- x="1.4415842"
- y="15.279208"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;writing-mode:lr-tb;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="3.3336635"
- y="8.7019796"
- id="text3029"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3031" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="3.1985149"
- y="11.314851"
- id="text3033"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3035" /></text>
- <text
- xml:space="preserve"
- style="font-size:30.70153999px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="1.6724377"
- y="14.187632"
- id="text3056"
- sodipodi:linespacing="122%"
- transform="scale(1.1043937,0.90547417)"><tspan
- sodipodi:role="line"
- id="tspan3058"
- x="1.6724377"
- y="14.187632"
- style="font-size:13.8156929px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;writing-mode:lr-tb;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans"> I</tspan></text>
- <path
- style="fill:#f5f5f5"
- d="m 6.4412871,12.555481 c 0,-0.189042 0.019349,-0.295299 0.056312,-0.309238 0.030971,-0.01168 0.3147676,-0.0696 0.630658,-0.128706 l 0.5743462,-0.10747 3.5e-5,-3.6143641 3.51e-5,-3.6143645 -0.1013614,-0.024151 C 7.5455631,4.7439042 7.2668193,4.6869003 6.9818812,4.6305119 L 6.4638119,4.5279874 6.4503998,4.2483591 6.4369878,3.9687307 l 1.9639528,0 1.9639524,0 -0.01341,0.2796578 -0.01341,0.2796578 -0.4054452,0.080633 C 9.7096287,4.6530275 9.4206285,4.7110942 9.290401,4.7377165 l -0.2367772,0.048404 0.01153,3.6112055 0.01153,3.6112059 0.540594,0.100942 c 0.8265408,0.154336 0.7433168,0.104843 0.7433168,0.442046 l 0,0.291963 -1.9596534,0 -1.9596535,0 0,-0.288002 z"
- id="path3439"
- inkscape:connector-curvature="0" />
- </g>
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg width="22" height="17">
+ <circle cx="0" cy="0" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="1" cy="0" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="2" cy="0" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="3" cy="0" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="4" cy="0" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="5" cy="0" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="6" cy="0" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="7" cy="0" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="8" cy="0" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="9" cy="0" r="1" fill="rgb(2,5,6)"/>
+ <circle cx="10" cy="0" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="11" cy="0" r="1" fill="rgb(6,15,28)"/>
+ <circle cx="12" cy="0" r="1" fill="rgb(42,104,154)"/>
+ <circle cx="13" cy="0" r="1" fill="rgb(5,7,14)"/>
+ <circle cx="14" cy="0" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="15" cy="0" r="1" fill="rgb(1,2,2)"/>
+ <circle cx="16" cy="0" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="17" cy="0" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="18" cy="0" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="19" cy="0" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="20" cy="0" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="21" cy="0" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="0" cy="1" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="1" cy="1" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="2" cy="1" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="3" cy="1" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="4" cy="1" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="5" cy="1" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="6" cy="1" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="7" cy="1" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="8" cy="1" r="1" fill="rgb(2,5,6)"/>
+ <circle cx="9" cy="1" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="10" cy="1" r="1" fill="rgb(10,21,38)"/>
+ <circle cx="11" cy="1" r="1" fill="rgb(60,158,208)"/>
+ <circle cx="12" cy="1" r="1" fill="rgb(78,191,243)"/>
+ <circle cx="13" cy="1" r="1" fill="rgb(43,96,135)"/>
+ <circle cx="14" cy="1" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="15" cy="1" r="1" fill="rgb(2,3,3)"/>
+ <circle cx="16" cy="1" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="17" cy="1" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="18" cy="1" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="19" cy="1" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="20" cy="1" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="21" cy="1" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="0" cy="2" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="1" cy="2" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="2" cy="2" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="3" cy="2" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="4" cy="2" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="5" cy="2" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="6" cy="2" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="7" cy="2" r="1" fill="rgb(2,4,5)"/>
+ <circle cx="8" cy="2" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="9" cy="2" r="1" fill="rgb(15,40,63)"/>
+ <circle cx="10" cy="2" r="1" fill="rgb(70,186,241)"/>
+ <circle cx="11" cy="2" r="1" fill="rgb(78,197,245)"/>
+ <circle cx="12" cy="2" r="1" fill="rgb(74,172,216)"/>
+ <circle cx="13" cy="2" r="1" fill="rgb(82,197,246)"/>
+ <circle cx="14" cy="2" r="1" fill="rgb(30,64,93)"/>
+ <circle cx="15" cy="2" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="16" cy="2" r="1" fill="rgb(2,4,5)"/>
+ <circle cx="17" cy="2" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="18" cy="2" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="19" cy="2" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="20" cy="2" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="21" cy="2" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="0" cy="3" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="1" cy="3" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="2" cy="3" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="3" cy="3" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="4" cy="3" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="5" cy="3" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="6" cy="3" r="1" fill="rgb(2,3,3)"/>
+ <circle cx="7" cy="3" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="8" cy="3" r="1" fill="rgb(22,57,92)"/>
+ <circle cx="9" cy="3" r="1" fill="rgb(73,196,252)"/>
+ <circle cx="10" cy="3" r="1" fill="rgb(76,205,252)"/>
+ <circle cx="11" cy="3" r="1" fill="rgb(73,171,219)"/>
+ <circle cx="12" cy="3" r="1" fill="rgb(75,174,224)"/>
+ <circle cx="13" cy="3" r="1" fill="rgb(80,195,237)"/>
+ <circle cx="14" cy="3" r="1" fill="rgb(78,186,236)"/>
+ <circle cx="15" cy="3" r="1" fill="rgb(15,27,46)"/>
+ <circle cx="16" cy="3" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="17" cy="3" r="1" fill="rgb(2,3,4)"/>
+ <circle cx="18" cy="3" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="19" cy="3" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="20" cy="3" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="21" cy="3" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="0" cy="4" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="1" cy="4" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="2" cy="4" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="3" cy="4" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="4" cy="4" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="5" cy="4" r="1" fill="rgb(2,3,3)"/>
+ <circle cx="6" cy="4" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="7" cy="4" r="1" fill="rgb(25,69,118)"/>
+ <circle cx="8" cy="4" r="1" fill="rgb(72,199,255)"/>
+ <circle cx="9" cy="4" r="1" fill="rgb(76,204,247)"/>
+ <circle cx="10" cy="4" r="1" fill="rgb(71,182,233)"/>
+ <circle cx="11" cy="4" r="1" fill="rgb(75,172,221)"/>
+ <circle cx="12" cy="4" r="1" fill="rgb(76,180,227)"/>
+ <circle cx="13" cy="4" r="1" fill="rgb(78,185,229)"/>
+ <circle cx="14" cy="4" r="1" fill="rgb(85,207,247)"/>
+ <circle cx="15" cy="4" r="1" fill="rgb(65,154,203)"/>
+ <circle cx="16" cy="4" r="1" fill="rgb(2,2,10)"/>
+ <circle cx="17" cy="4" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="18" cy="4" r="1" fill="rgb(1,2,2)"/>
+ <circle cx="19" cy="4" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="20" cy="4" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="21" cy="4" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="0" cy="5" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="1" cy="5" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="2" cy="5" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="3" cy="5" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="4" cy="5" r="1" fill="rgb(2,4,5)"/>
+ <circle cx="5" cy="5" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="6" cy="5" r="1" fill="rgb(17,51,93)"/>
+ <circle cx="7" cy="5" r="1" fill="rgb(68,195,255)"/>
+ <circle cx="8" cy="5" r="1" fill="rgb(73,199,239)"/>
+ <circle cx="9" cy="5" r="1" fill="rgb(69,192,241)"/>
+ <circle cx="10" cy="5" r="1" fill="rgb(71,171,228)"/>
+ <circle cx="11" cy="5" r="1" fill="rgb(78,176,228)"/>
+ <circle cx="12" cy="5" r="1" fill="rgb(77,180,227)"/>
+ <circle cx="13" cy="5" r="1" fill="rgb(80,189,233)"/>
+ <circle cx="14" cy="5" r="1" fill="rgb(80,194,234)"/>
+ <circle cx="15" cy="5" r="1" fill="rgb(89,218,255)"/>
+ <circle cx="16" cy="5" r="1" fill="rgb(48,112,154)"/>
+ <circle cx="17" cy="5" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="18" cy="5" r="1" fill="rgb(2,3,3)"/>
+ <circle cx="19" cy="5" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="20" cy="5" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="21" cy="5" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="0" cy="6" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="1" cy="6" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="2" cy="6" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="3" cy="6" r="1" fill="rgb(1,2,3)"/>
+ <circle cx="4" cy="6" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="5" cy="6" r="1" fill="rgb(5,13,30)"/>
+ <circle cx="6" cy="6" r="1" fill="rgb(57,167,233)"/>
+ <circle cx="7" cy="6" r="1" fill="rgb(71,198,242)"/>
+ <circle cx="8" cy="6" r="1" fill="rgb(67,194,241)"/>
+ <circle cx="9" cy="6" r="1" fill="rgb(65,177,233)"/>
+ <circle cx="10" cy="6" r="1" fill="rgb(69,161,215)"/>
+ <circle cx="11" cy="6" r="1" fill="rgb(71,167,219)"/>
+ <circle cx="12" cy="6" r="1" fill="rgb(76,180,226)"/>
+ <circle cx="13" cy="6" r="1" fill="rgb(81,192,234)"/>
+ <circle cx="14" cy="6" r="1" fill="rgb(80,195,234)"/>
+ <circle cx="15" cy="6" r="1" fill="rgb(82,206,237)"/>
+ <circle cx="16" cy="6" r="1" fill="rgb(86,208,255)"/>
+ <circle cx="17" cy="6" r="1" fill="rgb(27,62,98)"/>
+ <circle cx="18" cy="6" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="19" cy="6" r="1" fill="rgb(2,3,4)"/>
+ <circle cx="20" cy="6" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="21" cy="6" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="0" cy="7" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="1" cy="7" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="2" cy="7" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="3" cy="7" r="1" fill="rgb(1,3,3)"/>
+ <circle cx="4" cy="7" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="5" cy="7" r="1" fill="rgb(42,120,174)"/>
+ <circle cx="6" cy="7" r="1" fill="rgb(70,202,251)"/>
+ <circle cx="7" cy="7" r="1" fill="rgb(65,188,236)"/>
+ <circle cx="8" cy="7" r="1" fill="rgb(65,190,246)"/>
+ <circle cx="9" cy="7" r="1" fill="rgb(62,154,213)"/>
+ <circle cx="10" cy="7" r="1" fill="rgb(69,165,221)"/>
+ <circle cx="11" cy="7" r="1" fill="rgb(71,172,224)"/>
+ <circle cx="12" cy="7" r="1" fill="rgb(75,181,227)"/>
+ <circle cx="13" cy="7" r="1" fill="rgb(81,189,233)"/>
+ <circle cx="14" cy="7" r="1" fill="rgb(82,196,236)"/>
+ <circle cx="15" cy="7" r="1" fill="rgb(80,202,238)"/>
+ <circle cx="16" cy="7" r="1" fill="rgb(86,214,248)"/>
+ <circle cx="17" cy="7" r="1" fill="rgb(67,166,231)"/>
+ <circle cx="18" cy="7" r="1" fill="rgb(4,8,18)"/>
+ <circle cx="19" cy="7" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="20" cy="7" r="1" fill="rgb(1,2,2)"/>
+ <circle cx="21" cy="7" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="0" cy="8" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="1" cy="8" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="2" cy="8" r="1" fill="rgb(2,4,5)"/>
+ <circle cx="3" cy="8" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="4" cy="8" r="1" fill="rgb(23,63,99)"/>
+ <circle cx="5" cy="8" r="1" fill="rgb(70,198,252)"/>
+ <circle cx="6" cy="8" r="1" fill="rgb(66,188,236)"/>
+ <circle cx="7" cy="8" r="1" fill="rgb(62,192,247)"/>
+ <circle cx="8" cy="8" r="1" fill="rgb(53,164,230)"/>
+ <circle cx="9" cy="8" r="1" fill="rgb(57,137,194)"/>
+ <circle cx="10" cy="8" r="1" fill="rgb(63,153,211)"/>
+ <circle cx="11" cy="8" r="1" fill="rgb(69,165,219)"/>
+ <circle cx="12" cy="8" r="1" fill="rgb(75,176,225)"/>
+ <circle cx="13" cy="8" r="1" fill="rgb(76,185,229)"/>
+ <circle cx="14" cy="8" r="1" fill="rgb(82,195,235)"/>
+ <circle cx="15" cy="8" r="1" fill="rgb(82,205,239)"/>
+ <circle cx="16" cy="8" r="1" fill="rgb(89,217,245)"/>
+ <circle cx="17" cy="8" r="1" fill="rgb(74,183,235)"/>
+ <circle cx="18" cy="8" r="1" fill="rgb(7,14,26)"/>
+ <circle cx="19" cy="8" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="20" cy="8" r="1" fill="rgb(1,2,2)"/>
+ <circle cx="21" cy="8" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="0" cy="9" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="1" cy="9" r="1" fill="rgb(1,2,3)"/>
+ <circle cx="2" cy="9" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="3" cy="9" r="1" fill="rgb(7,16,31)"/>
+ <circle cx="4" cy="9" r="1" fill="rgb(60,177,233)"/>
+ <circle cx="5" cy="9" r="1" fill="rgb(66,195,243)"/>
+ <circle cx="6" cy="9" r="1" fill="rgb(60,185,241)"/>
+ <circle cx="7" cy="9" r="1" fill="rgb(61,172,233)"/>
+ <circle cx="8" cy="9" r="1" fill="rgb(61,162,221)"/>
+ <circle cx="9" cy="9" r="1" fill="rgb(58,150,211)"/>
+ <circle cx="10" cy="9" r="1" fill="rgb(58,143,204)"/>
+ <circle cx="11" cy="9" r="1" fill="rgb(63,156,212)"/>
+ <circle cx="12" cy="9" r="1" fill="rgb(69,172,227)"/>
+ <circle cx="13" cy="9" r="1" fill="rgb(74,185,231)"/>
+ <circle cx="14" cy="9" r="1" fill="rgb(76,193,233)"/>
+ <circle cx="15" cy="9" r="1" fill="rgb(80,203,239)"/>
+ <circle cx="16" cy="9" r="1" fill="rgb(90,218,247)"/>
+ <circle cx="17" cy="9" r="1" fill="rgb(74,184,228)"/>
+ <circle cx="18" cy="9" r="1" fill="rgb(5,10,21)"/>
+ <circle cx="19" cy="9" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="20" cy="9" r="1" fill="rgb(1,2,2)"/>
+ <circle cx="21" cy="9" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="0" cy="10" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="1" cy="10" r="1" fill="rgb(1,2,2)"/>
+ <circle cx="2" cy="10" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="3" cy="10" r="1" fill="rgb(42,124,174)"/>
+ <circle cx="4" cy="10" r="1" fill="rgb(64,196,250)"/>
+ <circle cx="5" cy="10" r="1" fill="rgb(61,174,229)"/>
+ <circle cx="6" cy="10" r="1" fill="rgb(75,182,230)"/>
+ <circle cx="7" cy="10" r="1" fill="rgb(93,198,236)"/>
+ <circle cx="8" cy="10" r="1" fill="rgb(104,202,233)"/>
+ <circle cx="9" cy="10" r="1" fill="rgb(103,206,238)"/>
+ <circle cx="10" cy="10" r="1" fill="rgb(67,162,220)"/>
+ <circle cx="11" cy="10" r="1" fill="rgb(56,147,212)"/>
+ <circle cx="12" cy="10" r="1" fill="rgb(67,173,230)"/>
+ <circle cx="13" cy="10" r="1" fill="rgb(73,183,234)"/>
+ <circle cx="14" cy="10" r="1" fill="rgb(76,192,235)"/>
+ <circle cx="15" cy="10" r="1" fill="rgb(80,198,238)"/>
+ <circle cx="16" cy="10" r="1" fill="rgb(85,213,246)"/>
+ <circle cx="17" cy="10" r="1" fill="rgb(73,181,223)"/>
+ <circle cx="18" cy="10" r="1" fill="rgb(4,7,16)"/>
+ <circle cx="19" cy="10" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="20" cy="10" r="1" fill="rgb(1,2,2)"/>
+ <circle cx="21" cy="10" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="0" cy="11" r="1" fill="rgb(2,3,4)"/>
+ <circle cx="1" cy="11" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="2" cy="11" r="1" fill="rgb(22,57,93)"/>
+ <circle cx="3" cy="11" r="1" fill="rgb(76,203,255)"/>
+ <circle cx="4" cy="11" r="1" fill="rgb(84,194,234)"/>
+ <circle cx="5" cy="11" r="1" fill="rgb(99,203,234)"/>
+ <circle cx="6" cy="11" r="1" fill="rgb(114,219,241)"/>
+ <circle cx="7" cy="11" r="1" fill="rgb(121,227,244)"/>
+ <circle cx="8" cy="11" r="1" fill="rgb(116,220,239)"/>
+ <circle cx="9" cy="11" r="1" fill="rgb(117,222,241)"/>
+ <circle cx="10" cy="11" r="1" fill="rgb(115,222,244)"/>
+ <circle cx="11" cy="11" r="1" fill="rgb(78,184,231)"/>
+ <circle cx="12" cy="11" r="1" fill="rgb(59,164,227)"/>
+ <circle cx="13" cy="11" r="1" fill="rgb(70,177,231)"/>
+ <circle cx="14" cy="11" r="1" fill="rgb(75,187,235)"/>
+ <circle cx="15" cy="11" r="1" fill="rgb(78,193,235)"/>
+ <circle cx="16" cy="11" r="1" fill="rgb(83,208,245)"/>
+ <circle cx="17" cy="11" r="1" fill="rgb(69,172,215)"/>
+ <circle cx="18" cy="11" r="1" fill="rgb(4,4,11)"/>
+ <circle cx="19" cy="11" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="20" cy="11" r="1" fill="rgb(1,2,2)"/>
+ <circle cx="21" cy="11" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="0" cy="12" r="1" fill="rgb(1,2,2)"/>
+ <circle cx="1" cy="12" r="1" fill="rgb(1,0,0)"/>
+ <circle cx="2" cy="12" r="1" fill="rgb(6,11,21)"/>
+ <circle cx="3" cy="12" r="1" fill="rgb(49,96,123)"/>
+ <circle cx="4" cy="12" r="1" fill="rgb(118,220,244)"/>
+ <circle cx="5" cy="12" r="1" fill="rgb(135,249,255)"/>
+ <circle cx="6" cy="12" r="1" fill="rgb(125,232,246)"/>
+ <circle cx="7" cy="12" r="1" fill="rgb(123,229,243)"/>
+ <circle cx="8" cy="12" r="1" fill="rgb(122,230,244)"/>
+ <circle cx="9" cy="12" r="1" fill="rgb(124,231,245)"/>
+ <circle cx="10" cy="12" r="1" fill="rgb(122,230,244)"/>
+ <circle cx="11" cy="12" r="1" fill="rgb(125,237,248)"/>
+ <circle cx="12" cy="12" r="1" fill="rgb(92,206,241)"/>
+ <circle cx="13" cy="12" r="1" fill="rgb(62,173,231)"/>
+ <circle cx="14" cy="12" r="1" fill="rgb(72,181,231)"/>
+ <circle cx="15" cy="12" r="1" fill="rgb(77,189,230)"/>
+ <circle cx="16" cy="12" r="1" fill="rgb(78,200,245)"/>
+ <circle cx="17" cy="12" r="1" fill="rgb(61,159,206)"/>
+ <circle cx="18" cy="12" r="1" fill="rgb(2,1,7)"/>
+ <circle cx="19" cy="12" r="1" fill="rgb(1,1,0)"/>
+ <circle cx="20" cy="12" r="1" fill="rgb(1,1,2)"/>
+ <circle cx="21" cy="12" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="0" cy="13" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="1" cy="13" r="1" fill="rgb(1,1,2)"/>
+ <circle cx="2" cy="13" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="3" cy="13" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="4" cy="13" r="1" fill="rgb(18,31,41)"/>
+ <circle cx="5" cy="13" r="1" fill="rgb(88,161,181)"/>
+ <circle cx="6" cy="13" r="1" fill="rgb(139,250,255)"/>
+ <circle cx="7" cy="13" r="1" fill="rgb(138,250,255)"/>
+ <circle cx="8" cy="13" r="1" fill="rgb(129,235,244)"/>
+ <circle cx="9" cy="13" r="1" fill="rgb(128,233,245)"/>
+ <circle cx="10" cy="13" r="1" fill="rgb(127,236,247)"/>
+ <circle cx="11" cy="13" r="1" fill="rgb(131,238,250)"/>
+ <circle cx="12" cy="13" r="1" fill="rgb(134,246,252)"/>
+ <circle cx="13" cy="13" r="1" fill="rgb(106,224,248)"/>
+ <circle cx="14" cy="13" r="1" fill="rgb(69,180,233)"/>
+ <circle cx="15" cy="13" r="1" fill="rgb(75,181,227)"/>
+ <circle cx="16" cy="13" r="1" fill="rgb(77,200,246)"/>
+ <circle cx="17" cy="13" r="1" fill="rgb(56,148,198)"/>
+ <circle cx="18" cy="13" r="1" fill="rgb(1,0,3)"/>
+ <circle cx="19" cy="13" r="1" fill="rgb(1,1,0)"/>
+ <circle cx="20" cy="13" r="1" fill="rgb(1,1,2)"/>
+ <circle cx="21" cy="13" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="0" cy="14" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="1" cy="14" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="2" cy="14" r="1" fill="rgb(1,2,2)"/>
+ <circle cx="3" cy="14" r="1" fill="rgb(2,4,5)"/>
+ <circle cx="4" cy="14" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="5" cy="14" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="6" cy="14" r="1" fill="rgb(40,69,85)"/>
+ <circle cx="7" cy="14" r="1" fill="rgb(111,200,223)"/>
+ <circle cx="8" cy="14" r="1" fill="rgb(145,255,255)"/>
+ <circle cx="9" cy="14" r="1" fill="rgb(139,248,252)"/>
+ <circle cx="10" cy="14" r="1" fill="rgb(135,242,247)"/>
+ <circle cx="11" cy="14" r="1" fill="rgb(134,241,248)"/>
+ <circle cx="12" cy="14" r="1" fill="rgb(134,240,247)"/>
+ <circle cx="13" cy="14" r="1" fill="rgb(136,244,248)"/>
+ <circle cx="14" cy="14" r="1" fill="rgb(113,227,244)"/>
+ <circle cx="15" cy="14" r="1" fill="rgb(72,179,225)"/>
+ <circle cx="16" cy="14" r="1" fill="rgb(73,186,235)"/>
+ <circle cx="17" cy="14" r="1" fill="rgb(53,134,187)"/>
+ <circle cx="18" cy="14" r="1" fill="rgb(1,0,1)"/>
+ <circle cx="19" cy="14" r="1" fill="rgb(1,2,1)"/>
+ <circle cx="20" cy="14" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="21" cy="14" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="0" cy="15" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="1" cy="15" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="2" cy="15" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="3" cy="15" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="4" cy="15" r="1" fill="rgb(2,3,3)"/>
+ <circle cx="5" cy="15" r="1" fill="rgb(2,3,3)"/>
+ <circle cx="6" cy="15" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="7" cy="15" r="1" fill="rgb(3,3,11)"/>
+ <circle cx="8" cy="15" r="1" fill="rgb(58,103,131)"/>
+ <circle cx="9" cy="15" r="1" fill="rgb(114,208,241)"/>
+ <circle cx="10" cy="15" r="1" fill="rgb(133,241,255)"/>
+ <circle cx="11" cy="15" r="1" fill="rgb(141,250,255)"/>
+ <circle cx="12" cy="15" r="1" fill="rgb(144,255,255)"/>
+ <circle cx="13" cy="15" r="1" fill="rgb(141,254,255)"/>
+ <circle cx="14" cy="15" r="1" fill="rgb(142,255,255)"/>
+ <circle cx="15" cy="15" r="1" fill="rgb(131,245,255)"/>
+ <circle cx="16" cy="15" r="1" fill="rgb(94,219,255)"/>
+ <circle cx="17" cy="15" r="1" fill="rgb(46,127,182)"/>
+ <circle cx="18" cy="15" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="19" cy="15" r="1" fill="rgb(1,2,2)"/>
+ <circle cx="20" cy="15" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="21" cy="15" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="0" cy="16" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="1" cy="16" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="2" cy="16" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="3" cy="16" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="4" cy="16" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="5" cy="16" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="6" cy="16" r="1" fill="rgb(3,5,5)"/>
+ <circle cx="7" cy="16" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="8" cy="16" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="9" cy="16" r="1" fill="rgb(16,28,44)"/>
+ <circle cx="10" cy="16" r="1" fill="rgb(43,77,102)"/>
+ <circle cx="11" cy="16" r="1" fill="rgb(54,92,112)"/>
+ <circle cx="12" cy="16" r="1" fill="rgb(64,111,126)"/>
+ <circle cx="13" cy="16" r="1" fill="rgb(70,125,139)"/>
+ <circle cx="14" cy="16" r="1" fill="rgb(74,133,147)"/>
+ <circle cx="15" cy="16" r="1" fill="rgb(78,142,156)"/>
+ <circle cx="16" cy="16" r="1" fill="rgb(82,157,175)"/>
+ <circle cx="17" cy="16" r="1" fill="rgb(40,91,130)"/>
+ <circle cx="18" cy="16" r="1" fill="rgb(0,0,0)"/>
+ <circle cx="19" cy="16" r="1" fill="rgb(1,2,1)"/>
+ <circle cx="20" cy="16" r="1" fill="rgb(1,1,1)"/>
+ <circle cx="21" cy="16" r="1" fill="rgb(1,1,1)"/>
</svg>
diff --git a/icons/left_bottom.svg b/icons/left_bottom.svg
index 8018d15..b1f0529 100644
--- a/icons/left_bottom.svg
+++ b/icons/left_bottom.svg
@@ -9,35 +9,14 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16px"
- height="16px"
- id="svg3017"
- version="1.1"
+ version="1.0"
+ width="55"
+ height="55"
+ id="svg2"
inkscape:version="0.48.0 r9654"
sodipodi:docname="left_bottom.svg">
- <defs
- id="defs3019" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="22.197802"
- inkscape:cx="8"
- inkscape:cy="10.328398"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
- inkscape:window-width="1366"
- inkscape:window-height="701"
- inkscape:window-x="0"
- inkscape:window-y="0"
- inkscape:window-maximized="1" />
<metadata
- id="metadata3022">
+ id="metadata13">
<rdf:RDF>
<cc:Work
rdf:about="">
@@ -48,227 +27,190 @@
</cc:Work>
</rdf:RDF>
</metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1366"
+ inkscape:window-height="701"
+ id="namedview11"
+ showgrid="false"
+ inkscape:zoom="5.4545455"
+ inkscape:cx="27.5"
+ inkscape:cy="24.186576"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2"
+ showguides="true"
+ inkscape:guide-bbox="true" />
+ <defs
+ id="defs5" />
+ <text
+ xml:space="preserve"
+ style="font-size:6px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+ x="3.3"
+ y="12.65"
+ id="text3004"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3006"
+ x="3.3"
+ y="12.65" /></text>
+ <text
+ xml:space="preserve"
+ style="font-size:6px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+ x="41.25"
+ y="11.183333"
+ id="text3144"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3146"
+ x="41.25"
+ y="11.183333" /></text>
+ <path
+ d="m 50.533944,27.958334 c 0,11.48326 -9.861205,20.792279 -22.025613,20.792279 -12.164408,0 -22.0256101,-9.309019 -22.0256101,-20.792279 0,-11.483258 9.8612021,-20.7922796 22.0256101,-20.7922796 12.164408,0 22.025613,9.3090216 22.025613,20.7922796 l 0,0 z"
+ id="path2387"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:3.69877648;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
<g
- id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="1.4415842"
- y="15.279208"
- id="text3025"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3027"
- x="1.4415842"
- y="15.279208"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;writing-mode:lr-tb;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="3.3336635"
- y="8.7019796"
- id="text3029"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3031" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="3.1985149"
- y="11.314851"
- id="text3033"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3035" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="1.8920792"
- y="14.062871"
- id="text3056"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3058"
- x="1.8920792"
- y="14.062871"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;writing-mode:lr-tb;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans"> </tspan></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122%;letter-spacing:0px;word-spacing:0px;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.2163366"
- y="3.791584"
- id="text3117"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3119"
- x="1.2163366"
- y="3.791584" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="8.9198017"
- y="4.5123763"
- id="text3154"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- x="8.9198017"
- y="4.5123763"
- id="tspan3158" /><tspan
- sodipodi:role="line"
- x="8.9198017"
- y="14.272377"
- id="tspan3160" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="2.0722773"
- y="14.738614"
- id="text3162"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3164"
- x="2.0722773"
- y="14.738614" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.0361387"
- y="15.144059"
- id="text3166"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3168"
- x="1.0361387"
- y="15.144059" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="0.58564359"
- y="4.1069307"
- id="text3191"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3193" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.0811881"
- y="10.278713"
- id="text3216"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- x="1.0811881"
- y="10.278713"
- id="tspan3220" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.0811881"
- y="15.459406"
- id="text3224"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3226"
- x="1.0811881"
- y="15.459406">L-B</tspan></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.4415842"
- y="6.8099008"
- id="text3228"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3230"
- x="1.4415842"
- y="6.8099008" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="0.27029702"
- y="6.8099008"
- id="text3232"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3234"
- x="0.27029702"
- y="6.8099008">text edit</tspan></text>
- <path
- style="fill:#ffffff"
- d="m 1.0080716,5.5679881 c 7.03e-5,-0.3468812 0.00714,-0.4828321 0.015715,-0.3021132 0.00857,0.1807189 0.00852,0.4645308 -1.278e-4,0.6306931 -0.00864,0.1661623 -0.015657,0.018301 -0.015587,-0.3285799 z"
- id="path3078"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 0.9998435,6.8024538 C 0.91017723,6.775747 0.81690142,6.7012352 0.76350199,6.6136564 0.6849364,6.4848036 0.6752688,6.3839765 0.67511883,5.6918743 l -1.684e-4,-0.777104 -0.15767327,0 c -0.20450798,0 -0.20678618,-0.095041 -0.004589,-0.1914616 0.12121407,-0.057803 0.1688609,-0.1205011 0.228868,-0.3011655 0.0560095,-0.1686289 0.0983495,-0.228165 0.16226278,-0.228165 0.0747894,0 0.0864785,0.033491 0.0864785,0.2477723 l 0,0.2477723 0.27029703,0 c 0.2582838,0 0.270297,0.00501 0.270297,0.1126237 0,0.1076183 -0.012013,0.1126238 -0.270297,0.1126238 l -0.27029703,0 0,0.7588595 c 0,0.8685819 0.0153003,0.9079722 0.35268093,0.9079722 0.1559756,0 0.1879131,0.014861 0.1879131,0.08744 0,0.048092 -0.015359,0.096933 -0.03413,0.108534 -0.082981,0.051285 -0.3614494,0.065226 -0.4969173,0.024878 z"
- id="path3080"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 2.5531488,6.7885855 C 2.2891192,6.7163791 2.0544255,6.5002315 1.9537124,6.236518 1.8388849,5.9358466 1.8826174,5.3522224 2.0401126,5.0834771 2.3240392,4.598993 2.9171221,4.5202209 3.2947898,4.9168334 c 0.1610986,0.1691798 0.263329,0.4578123 0.263329,0.7434711 l 0,0.1104064 -0.6820176,0 -0.6820176,0 0.026866,0.2268396 c 0.053704,0.4534426 0.3428047,0.6417658 0.8416248,0.5482426 0.1362748,-0.02555 0.2832488,-0.060523 0.3266089,-0.077717 0.064326,-0.025508 0.078837,-0.00681 0.078837,0.1015753 0,0.1148629 -0.022859,0.1393871 -0.1689357,0.1812414 -0.302798,0.086759 -0.5253919,0.098006 -0.7459353,0.037693 l 0,0 z M 3.1977227,5.4080777 c 0,-0.1698534 -0.1072985,-0.3851335 -0.2227522,-0.4469224 -0.1459494,-0.07811 -0.4301392,-0.054802 -0.5579871,0.045763 -0.1038301,0.081673 -0.2093924,0.323967 -0.2100986,0.4822331 -1.858e-4,0.041652 0.1287567,0.056312 0.4952934,0.056312 l 0.4955445,0 0,-0.1373857 z"
- id="path3082"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 4.2369013,6.2617179 4.6021163,5.7165864 4.2600996,5.2030546 3.9180829,4.6895228 l 0.1712048,0 c 0.1673451,0 0.1767445,0.00914 0.4169239,0.4052906 C 4.6413571,5.3177232 4.7620668,5.49969 4.7744554,5.4991839 4.786844,5.4986779 4.9042885,5.3162972 5.0354432,5.0938934 5.2625701,4.7087458 5.2813088,4.6895228 5.4296264,4.6895228 c 0.085646,0 0.1557201,0.010812 0.1557201,0.024027 0,0.013214 -0.1434506,0.2378362 -0.3187793,0.4991592 -0.1753285,0.261323 -0.3079789,0.5032778 -0.2947785,0.5376775 0.0132,0.0344 0.1667872,0.2753646 0.341304,0.5354777 0.1745168,0.2601131 0.3173033,0.4837448 0.3173033,0.4969594 0,0.013215 -0.070111,0.024026 -0.1558024,0.024026 -0.1484334,0 -0.1681427,-0.020223 -0.416708,-0.4275671 C 4.9143876,6.1441205 4.7845492,5.9515339 4.7693558,5.9513121 4.7541624,5.9510903 4.6252122,6.1434956 4.4827998,6.3788792 4.2266091,6.8023195 4.2220044,6.8068495 4.0477773,6.8068495 l -0.176091,0 0.365215,-0.5451316 z"
- id="path3084"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 6.4863366,6.7944955 C 6.2143608,6.6992443 6.1711413,6.5450045 6.1710601,5.6693495 l -7e-5,-0.7545792 -0.1576733,0 c -0.204508,0 -0.2067862,-0.095041 -0.00459,-0.1914616 0.1212141,-0.057803 0.1688609,-0.1205011 0.228868,-0.3011655 0.05601,-0.1686289 0.09835,-0.228165 0.1622628,-0.228165 0.074789,0 0.086478,0.033491 0.086478,0.2477723 l 0,0.2477723 0.2702971,0 c 0.2582838,0 0.270297,0.00501 0.270297,0.1126237 0,0.1076183 -0.012013,0.1126238 -0.270297,0.1126238 l -0.2702971,0 0,0.7332931 c 0,0.8719524 0.022458,0.9335386 0.3404258,0.9335386 0.1681065,0 0.2001683,0.014006 0.2001683,0.08744 0,0.048092 -0.015359,0.096933 -0.03413,0.108534 -0.092212,0.05699 -0.3659374,0.066134 -0.5064639,0.016919 z"
- id="path3086"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d=""
- id="path3088"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 9.1169877,6.8025921 C 8.6876913,6.7015798 8.4234654,6.2989609 8.4234654,5.745825 c 0,-0.3581282 0.097634,-0.6309877 0.2999517,-0.8382781 0.5297235,-0.542744 1.3654209,-0.1182216 1.3666289,0.6942284 l 2.51e-4,0.1689356 -0.6757425,0 -0.6757426,0 0,0.1481277 c 0,0.08147 0.045613,0.2385805 0.1013614,0.3491337 0.1341402,0.2660084 0.3397027,0.3440888 0.7320544,0.278062 0.1486634,-0.025018 0.3057736,-0.059827 0.3491337,-0.077354 0.064463,-0.026057 0.078837,-0.00765 0.078837,0.1009709 0,0.1145403 -0.023269,0.1397547 -0.1689356,0.1830565 -0.2679836,0.079663 -0.5145374,0.096882 -0.7142747,0.049884 l 0,0 z M 9.729901,5.4080777 C 9.729901,5.2382243 9.6226025,5.0229442 9.5071488,4.9611553 9.2579802,4.8278043 8.9205372,4.9579619 8.8119701,5.2292978 8.6842446,5.5485152 8.6801676,5.5454634 9.2343564,5.5454634 l 0.4955446,0 0,-0.1373857 z"
- id="path3090"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 11.177017,6.806756 C 10.954583,6.7542393 10.805634,6.625006 10.679377,6.3749855 10.584704,6.1875088 10.56775,6.0915802 10.568603,5.7481862 c 0.0015,-0.6218861 0.191126,-0.9477891 0.618246,-1.0628004 0.225892,-0.060827 0.456978,-0.00187 0.633338,0.16157 0.06698,0.062075 0.130874,0.112864 0.141986,0.112864 0.01111,0 0.0202,-0.2635396 0.0202,-0.5856436 l 0,-0.5856435 0.157674,0 0.157673,0 0,1.5091584 0,1.5091584 -0.135149,0 c -0.109916,0 -0.135277,-0.018924 -0.135838,-0.1013614 -0.0014,-0.1988149 -0.06381,-0.2231121 -0.2022,-0.078663 -0.106728,0.1114004 -0.379271,0.2383256 -0.472853,0.2202111 -0.01239,-0.0024 -0.09099,-0.020524 -0.174666,-0.04028 z m 0.530954,-0.2906038 c 0.18785,-0.097141 0.25201,-0.299197 0.251007,-0.7904908 -0.0012,-0.6116031 -0.138456,-0.8108911 -0.55829,-0.8108911 -0.347892,0 -0.508317,0.2592534 -0.511932,0.8273036 -0.0025,0.3872383 0.06932,0.6266705 0.224491,0.7487247 0.137527,0.1081785 0.411936,0.1198768 0.594724,0.025354 z"
- id="path3092"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="m 13.018515,5.7481862 0,-1.0586634 0.157673,0 0.157673,0 0,1.0586634 0,1.0586633 -0.157673,0 -0.157673,0 0,-1.0586633 z"
- id="path3094"
- inkscape:connector-curvature="0" />
+ transform="matrix(1.0518195,0.08666257,-0.06158312,0.96746253,1.7575581,-2.3823119)"
+ id="g2937-8">
<path
- style="fill:#ffffff"
- d="M 14.424596,6.8024538 C 14.33493,6.775747 14.241654,6.7012352 14.188255,6.6136564 14.109689,6.4848036 14.100021,6.3839765 14.099871,5.6918743 l -1.68e-4,-0.777104 -0.157673,0 c -0.200928,0 -0.208019,-0.094959 -0.01395,-0.1868666 0.10999,-0.05209 0.16107,-0.1200886 0.217646,-0.2897326 0.05461,-0.163758 0.09945,-0.2254289 0.171627,-0.2360637 0.09026,-0.0133 0.0977,0.0047 0.0977,0.2365099 l 0,0.2509055 0.270297,0 c 0.258283,0 0.270297,0.00501 0.270297,0.1126237 0,0.1076183 -0.01201,0.1126238 -0.270297,0.1126238 l -0.270297,0 0,0.7588595 c 0,0.8685819 0.0153,0.9079722 0.35268,0.9079722 0.155976,0 0.187914,0.014861 0.187914,0.08744 0,0.048092 -0.01536,0.096933 -0.03413,0.108534 -0.08298,0.051285 -0.361449,0.065226 -0.496917,0.024878 z"
- id="path3096"
+ d="m 27.567493,45.252146 c -0.46948,0 -0.933016,-0.02903 -1.389761,-0.08296 l 1.178368,1.948634 1.161389,-1.918769 c -0.314968,0.02489 -0.629086,0.05309 -0.949996,0.05309 z"
+ id="path3003-9"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d="m 1.4858415,14.037295 0,-1.419059 0.1576733,0 0.1576733,0 0,1.283911 0,1.283911 0.5631188,0 0.5631188,0 0,0.135148 0,0.135149 -0.7207921,0 -0.7207921,0 0,-1.41906 z"
- id="path3098"
+ d="m 38.317981,14.929279 c -1.837168,0 -3.360217,1.289964 -3.68707,2.992219 1.578232,1.115757 2.934884,2.584076 3.968928,4.320343 1.939893,-0.142684 3.475677,-1.709721 3.475677,-3.641764 0,-2.027442 -1.682656,-3.670798 -3.757535,-3.670798 z"
+ id="path3007-2"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d="m 3.2427722,14.397691 0,-0.157673 0.4504951,0 0.450495,0 0,0.157673 0,0.157673 -0.450495,0 -0.4504951,0 0,-0.157673 z"
- id="path3100"
+ d="m 38.787461,38.290488 c -1.039138,1.851575 -2.42805,3.426908 -4.072502,4.609029 0.442312,1.546298 1.878767,2.686942 3.603022,2.686942 2.07403,0 3.757535,-1.642527 3.757535,-3.669969 0,-1.870656 -1.437304,-3.397874 -3.288055,-3.626002 z"
+ id="path3009-6"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d="m 4.7294059,14.034868 0,-1.430127 0.599739,0.02515 c 0.6491718,0.02722 0.837052,0.07851 1.0220432,0.278995 0.09545,0.103447 0.1126238,0.165604 0.1126238,0.407622 0,0.240143 -0.017354,0.304035 -0.1091055,0.401701 -0.060008,0.06387 -0.1765736,0.140534 -0.2590347,0.170352 -0.1560684,0.05644 -0.2006072,0.126214 -0.08056,0.126214 0.038153,0 0.1511839,0.04174 0.2511799,0.09275 0.4664891,0.237985 0.3901501,0.986188 -0.1265456,1.240281 -0.1357129,0.06674 -0.3006743,0.08775 -0.7909092,0.100759 l -0.6194307,0.01643 0,-1.430127 z m 1.2090694,1.081267 c 0.2099752,-0.08402 0.2925808,-0.222204 0.2925808,-0.48945 0,-0.391733 -0.2020517,-0.521093 -0.8146452,-0.521564 l -0.3266089,-2.52e-4 0,0.540594 0,0.540595 0.3369596,0 c 0.1994567,0 0.4082714,-0.02853 0.5117137,-0.06992 l 0,0 z m 0.1287829,-1.436227 c 0.096934,-0.112745 0.1105012,-0.164483 0.092435,-0.352497 -0.011646,-0.121197 -0.05156,-0.250744 -0.088699,-0.287883 -0.091184,-0.09118 -0.3592259,-0.148621 -0.6996336,-0.149921 l -0.2815594,-0.0011 0,0.477368 0,0.477369 0.4319236,-0.01561 c 0.4132738,-0.01494 0.4368292,-0.02132 0.5455326,-0.147751 z"
- id="path3102"
+ d="m 16.340734,38.277215 c -1.912727,0.170889 -3.41625,1.724653 -3.41625,3.639275 0,2.026612 1.680958,3.669969 3.755837,3.669969 1.752271,0 3.212497,-1.177974 3.626793,-2.764091 -1.598607,-1.174655 -2.950165,-2.728419 -3.96638,-4.545153 z"
+ id="path3011-6"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d=""
- id="path3235"
+ d="m 20.375881,18.007772 c -0.291196,-1.744563 -1.828678,-3.078493 -3.69556,-3.078493 -2.074879,0 -3.755837,1.643356 -3.755837,3.669968 0,1.97601 1.601155,3.575399 3.603872,3.655037 1.006876,-1.694789 2.319381,-3.139051 3.847525,-4.246512 z"
+ id="path3013-4"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d="m 13.01996,4.1966781 c -0.03401,-0.063551 -0.03536,-0.1195254 -0.0043,-0.1775979 0.107644,-0.2011345 0.336943,-0.1203114 0.310786,0.1095453 -0.01206,0.1060051 -0.0396,0.1357548 -0.135983,0.1468893 -0.08514,0.00984 -0.135534,-0.013462 -0.170521,-0.078837 z"
- id="path3237"
+ d="m 27.567493,15.62362 c 1.619832,0 3.164955,0.340948 4.599711,0.935742 0.629086,-0.892605 1.000085,-1.971862 1.000085,-3.138221 0,-3.058584 -2.537567,-5.5389654 -5.668563,-5.5389654 -3.130146,0 -5.667713,2.4803814 -5.667713,5.5389654 0,1.18461 0.383734,2.280457 1.032345,3.180529 1.463622,-0.62134 3.04525,-0.97805 4.704135,-0.97805 z"
+ id="path3015-9"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3017-5"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none">
+ <path
+ d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z"
+ id="path3019-0"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3021-4"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none">
+ <path
+ d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z"
+ id="path3023-8"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z"
+ id="path3025-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z"
+ id="path3027-1"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z"
+ id="path3029-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z"
+ id="path3031-2"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z"
+ id="path3033-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
</g>
+ <path
+ inkscape:connector-curvature="0"
+ d="m 35.076108,14.283991 2.437818,-2.366117 1.200984,0.84248 1.416085,1.200984 0.985882,1.272684 0.914181,1.487786 -2.366117,2.509519 -0.896257,-1.505711 -2.186866,-2.366117 -1.50571,-1.075508 z"
+ id="path3255"
+ style="fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:1px;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 32.387339,17.04446 2.294417,-2.079315 1.200984,0.84248 1.416085,1.200984 0.985882,1.272684 0.914181,1.487786 -2.079315,1.864214 -0.967957,-1.147208 -2.330267,-2.222716 -1.43401,-1.218909 z"
+ id="path3253"
+ style="fill:#000000;stroke:#ffffff;stroke-width:1px;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 12.933049,39.739227 0.891754,-3.80169 18.820708,-18.21056 -0.469344,-0.680549 2.252852,-2.135517 5.115854,5.115853 -2.229385,2.135517 -0.774419,-0.539747 -19.05538,18.022823 -3.70782,0.657082 -0.84482,-0.563212 z"
+ id="path2822"
+ style="fill:#000000;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 32.992233,18.29019 3.660886,3.473148"
+ id="path3596"
+ style="fill:#000000;stroke:#ffffff;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 10.445524,42.836899 2.769132,-2.816066"
+ id="path3598"
+ style="fill:#000000;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 14.200279,36.219143 c 0,0 1.594197,0.393866 2.158983,0.93869 0.574138,0.553844 1.032558,2.158984 1.032558,2.158984"
+ id="path3600"
+ style="fill:#000000;stroke:#ffffff;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
+ <path
+ style="fill:#ffffff"
+ d="M 17.697395,36.715165 C 17.52718,36.418583 17.133837,36.021412 16.823299,35.832563 l -0.564614,-0.343363 8.07,-7.818797 c 4.438499,-4.300338 8.135227,-7.818797 8.214949,-7.818797 0.07972,0 0.552,0.413263 1.049504,0.918363 l 0.904554,0.918362 -0.544779,0.523798 c -0.299628,0.288088 -3.721029,3.517184 -7.603112,7.175768 -3.882083,3.658584 -7.347366,6.925242 -7.700629,7.25924 l -0.642296,0.607268 -0.309481,-0.53924 z"
+ id="path2990"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff"
+ d="m 39.435184,17.676623 c -0.385066,-0.605404 -2.215315,-2.562189 -2.900953,-3.101512 l -0.446583,-0.351282 0.773579,-0.759211 0.773579,-0.75921 1.103351,0.892762 c 0.606843,0.49102 1.4187,1.350636 1.804126,1.910257 l 0.700775,1.017495 -0.368509,0.517008 c -0.202679,0.284355 -0.532115,0.664852 -0.732079,0.845549 -0.352751,0.318761 -0.373799,0.312457 -0.707286,-0.211856 l 0,0 z"
+ id="path2992"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff"
+ d="m 35.592157,18.866838 c -1.333982,-1.264073 -1.591222,-1.592584 -1.400927,-1.789073 0.190815,-0.197026 0.522406,0.04863 1.828095,1.354317 1.122173,1.122174 1.537468,1.652532 1.400927,1.789073 -0.136541,0.136541 -0.678467,-0.264937 -1.828095,-1.354317 l 0,0 z"
+ id="path2994"
+ inkscape:connector-curvature="0" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+ x="0.42647088"
+ y="53.731606"
+ id="text3002"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3004"
+ x="0.42647088"
+ y="53.731606">Left</tspan></text>
</svg>
diff --git a/icons/left_top.svg b/icons/left_top.svg
index e5033f5..c6312e4 100644
--- a/icons/left_top.svg
+++ b/icons/left_top.svg
@@ -9,35 +9,14 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16px"
- height="16px"
- id="svg3017"
- version="1.1"
+ version="1.0"
+ width="55"
+ height="55"
+ id="svg2"
inkscape:version="0.48.0 r9654"
sodipodi:docname="left_top.svg">
- <defs
- id="defs3019" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="22.197802"
- inkscape:cx="8"
- inkscape:cy="10.328398"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
- inkscape:window-width="1366"
- inkscape:window-height="701"
- inkscape:window-x="0"
- inkscape:window-y="0"
- inkscape:window-maximized="1" />
<metadata
- id="metadata3022">
+ id="metadata13">
<rdf:RDF>
<cc:Work
rdf:about="">
@@ -48,250 +27,190 @@
</cc:Work>
</rdf:RDF>
</metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1366"
+ inkscape:window-height="701"
+ id="namedview11"
+ showgrid="false"
+ inkscape:zoom="5.4545455"
+ inkscape:cx="27.5"
+ inkscape:cy="22.357136"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2"
+ showguides="true"
+ inkscape:guide-bbox="true" />
+ <defs
+ id="defs5" />
+ <text
+ xml:space="preserve"
+ style="font-size:6px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+ x="3.3"
+ y="12.65"
+ id="text3004"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3006"
+ x="3.3"
+ y="12.65" /></text>
+ <text
+ xml:space="preserve"
+ style="font-size:6px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+ x="41.25"
+ y="11.183333"
+ id="text3144"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3146"
+ x="41.25"
+ y="11.183333" /></text>
+ <path
+ d="m 50.992277,26.4 c 0,11.48326 -9.861205,20.792279 -22.025613,20.792279 -12.164408,0 -22.0256086,-9.309019 -22.0256086,-20.792279 0,-11.483257 9.8612006,-20.7922792 22.0256086,-20.7922792 12.164408,0 22.025613,9.3090222 22.025613,20.7922792 l 0,0 z"
+ id="path2387"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:3.69877648;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
<g
- id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="1.4415842"
- y="15.279208"
- id="text3025"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3027"
- x="1.4415842"
- y="15.279208"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;writing-mode:lr-tb;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="3.3336635"
- y="8.7019796"
- id="text3029"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3031" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="3.1985149"
- y="11.314851"
- id="text3033"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3035" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="1.8920792"
- y="14.062871"
- id="text3056"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3058"
- x="1.8920792"
- y="14.062871"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;writing-mode:lr-tb;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans"> </tspan></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122%;letter-spacing:0px;word-spacing:0px;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.2163366"
- y="3.791584"
- id="text3117"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3119"
- x="1.2163366"
- y="3.791584" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="8.9198017"
- y="4.5123763"
- id="text3154"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- x="8.9198017"
- y="4.5123763"
- id="tspan3158" /><tspan
- sodipodi:role="line"
- x="8.9198017"
- y="14.272377"
- id="tspan3160" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="2.0722773"
- y="14.738614"
- id="text3162"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3164"
- x="2.0722773"
- y="14.738614" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.0361387"
- y="15.144059"
- id="text3166"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3168"
- x="1.0361387"
- y="15.144059" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="0.58564359"
- y="4.1069307"
- id="text3191"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3193" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.0811881"
- y="10.278713"
- id="text3216"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- x="1.0811881"
- y="10.278713"
- id="tspan3220" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.0811881"
- y="15.459406"
- id="text3224"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3226"
- x="1.0811881"
- y="15.459406" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.4415842"
- y="6.8099008"
- id="text3228"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3230"
- x="1.4415842"
- y="6.8099008" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="0.27029702"
- y="6.8099008"
- id="text3232"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3234"
- x="0.27029702"
- y="6.8099008" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="9.7757425"
- y="15.234158"
- id="text3255"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3257"
- x="9.7757425"
- y="15.234158" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="0.58564359"
- y="4.3321781"
- id="text3278"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3280"
- x="0.58564359"
- y="4.3321781">L-T</tspan></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="0.58564359"
- y="12.035644"
- id="text3282"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3284"
- x="0.58564359"
- y="12.035644">text edit</tspan></text>
- <path
- style="fill:#ffffff"
- d="m 0.99029697,2.9100673 0,-1.4190594 0.15767323,0 0.1576733,0 0,1.2839109 0,1.2839109 0.5631188,0 0.5631188,0 0,0.1351485 0,0.1351485 -0.720792,0 -0.72079213,0 0,-1.4190594 z"
- id="path3209"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="m 2.7472277,3.2704634 0,-0.1576733 0.450495,0 0.4504951,0 0,0.1576733 0,0.1576732 -0.4504951,0 -0.450495,0 0,-0.1576732 z"
- id="path3211"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="m 4.5041584,3.0452158 0,-1.2839109 -0.4054456,0 -0.4054455,0 0,-0.1351485 0,-0.1351485 0.9910891,0 0.9910891,0 0,0.1351485 0,0.1351485 -0.4054455,0 -0.4054456,0 0,1.2839109 0,1.2839109 -0.180198,0 -0.180198,0 0,-1.2839109 z"
- id="path3213"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 1.31519,12.028196 C 1.2255238,12.00149 1.132248,11.926978 1.0788485,11.839399 1.0002829,11.710546 0.99061534,11.609719 0.99046537,10.917617 l -1.684e-4,-0.777104 -0.15767327,0 c -0.20450798,0 -0.20678618,-0.09504 -0.004589,-0.1914617 0.12121407,-0.057803 0.1688609,-0.1205011 0.22886799,-0.3011655 0.05601,-0.1686289 0.09835,-0.228165 0.1622628,-0.228165 0.074789,0 0.086478,0.033491 0.086478,0.2477723 l 0,0.2477723 0.270297,0 c 0.2582839,0 0.2702971,0.00501 0.2702971,0.1126236 0,0.107618 -0.012013,0.112624 -0.2702971,0.112624 l -0.270297,0 0,0.758859 c 0,0.868582 0.0153,0.907973 0.3526809,0.907973 0.1559756,0 0.1879132,0.01486 0.1879132,0.08744 0,0.04809 -0.015359,0.09693 -0.03413,0.108534 -0.082981,0.05129 -0.3614494,0.06523 -0.4969173,0.02488 z"
- id="path3215"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 2.8684953,12.014328 C 2.6044657,11.942122 2.369772,11.725974 2.2690589,11.462261 2.1542315,11.161589 2.1979639,10.577965 2.3554591,10.30922 2.6393857,9.8247356 3.2324686,9.7459636 3.6101364,10.142576 c 0.1610986,0.16918 0.2633289,0.457812 0.2633289,0.743471 l 0,0.110407 -0.6820176,0 -0.6820175,0 0.026866,0.226839 c 0.053703,0.453443 0.3428046,0.641766 0.8416248,0.548243 0.1362747,-0.02555 0.2832487,-0.06052 0.3266089,-0.07772 0.064326,-0.02551 0.078837,-0.0068 0.078837,0.101575 0,0.114863 -0.022859,0.139387 -0.1689356,0.181242 -0.3027981,0.08676 -0.525392,0.09801 -0.7459354,0.03769 l 0,0 z m 0.644574,-1.380508 c 0,-0.169853 -0.1072985,-0.385133 -0.2227522,-0.446922 -0.1459495,-0.07811 -0.4301392,-0.0548 -0.5579872,0.04576 -0.1038301,0.08167 -0.2093924,0.323967 -0.2100985,0.482233 -1.858e-4,0.04165 0.1287567,0.05631 0.4952933,0.05631 l 0.4955446,0 0,-0.137386 z"
- id="path3217"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 4.5522478,11.487461 4.9174629,10.942329 4.5754461,10.428797 4.2334294,9.9152654 l 0.1712048,0 c 0.1673451,0 0.1767446,0.00914 0.4169239,0.4052906 0.1351455,0.22291 0.2558552,0.404877 0.2682439,0.404371 0.012389,-5.06e-4 0.1298331,-0.182887 0.2609877,-0.405291 0.2271269,-0.3851475 0.2458657,-0.4043706 0.3941832,-0.4043706 0.085646,0 0.1557202,0.010812 0.1557202,0.024027 0,0.013215 -0.1434507,0.2378361 -0.3187793,0.4991591 -0.1753286,0.261323 -0.3079789,0.503278 -0.2947786,0.537678 0.0132,0.0344 0.1667872,0.275364 0.341304,0.535477 0.1745169,0.260113 0.3173034,0.483745 0.3173034,0.49696 0,0.01321 -0.070111,0.02403 -0.1558025,0.02403 -0.1484333,0 -0.1681426,-0.02022 -0.4167079,-0.427567 -0.143498,-0.235162 -0.2733365,-0.427749 -0.2885299,-0.42797 -0.015193,-2.22e-4 -0.1441435,0.192183 -0.2865559,0.427567 -0.2561908,0.42344 -0.2607955,0.42797 -0.4350226,0.42797 l -0.176091,0 0.365215,-0.545131 z"
- id="path3219"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 6.8016832,12.020238 C 6.5297073,11.924987 6.4864879,11.770747 6.4864066,10.895092 l -7e-5,-0.754579 -0.1576732,0 c -0.204508,0 -0.2067862,-0.09504 -0.00459,-0.1914617 0.121214,-0.057803 0.1688609,-0.1205011 0.228868,-0.3011655 0.056009,-0.1686289 0.098349,-0.228165 0.1622627,-0.228165 0.07479,0 0.086479,0.033491 0.086479,0.2477723 l 0,0.2477723 0.270297,0 c 0.2582838,0 0.270297,0.00501 0.270297,0.1126236 0,0.107618 -0.012013,0.112624 -0.270297,0.112624 l -0.270297,0 0,0.733293 c 0,0.871952 0.022458,0.933539 0.3404257,0.933539 0.1681065,0 0.2001683,0.01401 0.2001683,0.08744 0,0.04809 -0.015359,0.09693 -0.03413,0.108534 -0.092212,0.05699 -0.3659374,0.06613 -0.5064638,0.01692 z"
- id="path3221"
- inkscape:connector-curvature="0" />
+ transform="matrix(1.0518195,0.08666257,-0.06158312,0.96746253,2.2158924,-3.9406458)"
+ id="g2937-8">
<path
- style="fill:#ffffff"
- d="M 9.4323342,12.028335 C 9.0030378,11.927322 8.7388119,11.524703 8.7388119,10.971568 c 0,-0.358129 0.097634,-0.630988 0.2999517,-0.838278 0.5297235,-0.5427444 1.3654204,-0.118222 1.3666284,0.694228 l 2.52e-4,0.168936 -0.675743,0 -0.6757426,0 0,0.148127 c 0,0.08147 0.045613,0.238581 0.1013614,0.349134 0.1341402,0.266008 0.3397027,0.344089 0.7320545,0.278062 0.1486637,-0.02502 0.3057737,-0.05983 0.3491337,-0.07735 0.06446,-0.02606 0.07884,-0.0076 0.07884,0.100971 0,0.11454 -0.02327,0.139755 -0.168936,0.183057 -0.2679836,0.07966 -0.5145375,0.09688 -0.7142748,0.04988 l 0,0 z M 10.045248,10.63382 c 0,-0.169853 -0.107299,-0.385133 -0.2227526,-0.446922 -0.2491687,-0.133351 -0.5866117,-0.0032 -0.6951788,0.268142 -0.1277254,0.319218 -0.1318025,0.316166 0.4223864,0.316166 l 0.495545,0 0,-0.137386 z"
- id="path3223"
+ d="m 27.567493,45.252146 c -0.46948,0 -0.933016,-0.02903 -1.389761,-0.08296 l 1.178368,1.948634 1.161389,-1.918769 c -0.314968,0.02489 -0.629086,0.05309 -0.949996,0.05309 z"
+ id="path3003-9"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d="m 11.496598,11.691986 c -0.168243,-0.117842 -0.244741,-0.323737 -0.248635,-0.6692 -0.0043,-0.381224 0.06881,-0.623029 0.22568,-0.74642 0.222429,-0.174963 0.58167,-0.0773 0.693848,0.188631 0.08179,0.193894 0.08179,0.82397 0,1.017863 -0.10625,0.251878 -0.454759,0.360512 -0.670893,0.209126 z"
- id="path3225"
+ d="m 38.317981,14.929279 c -1.837168,0 -3.360217,1.289964 -3.68707,2.992219 1.578232,1.115757 2.934884,2.584076 3.968928,4.320343 1.939893,-0.142684 3.475677,-1.709721 3.475677,-3.641764 0,-2.027442 -1.682656,-3.670798 -3.757535,-3.670798 z"
+ id="path3007-2"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d="m 11.492364,12.032499 c -0.222435,-0.05252 -0.371384,-0.18175 -0.497641,-0.431771 -0.09467,-0.187477 -0.111626,-0.283405 -0.110774,-0.626799 0.0015,-0.621886 0.191127,-0.947789 0.618246,-1.0628006 0.225892,-0.060827 0.456979,-0.00187 0.633338,0.1615696 0.06698,0.06208 0.130874,0.112864 0.141986,0.112864 0.01111,0 0.0202,-0.2635392 0.0202,-0.5856431 l 0,-0.5856436 0.157673,0 0.157673,0 0,1.5091587 0,1.509158 -0.135148,0 c -0.109917,0 -0.135277,-0.01892 -0.135839,-0.101361 -0.0014,-0.198815 -0.06381,-0.223112 -0.202199,-0.07866 -0.106728,0.1114 -0.379271,0.238326 -0.472853,0.220211 -0.01239,-0.0024 -0.09099,-0.02052 -0.174666,-0.04028 z m 0.530954,-0.290604 c 0.18785,-0.09714 0.252009,-0.299197 0.251006,-0.790491 -0.0012,-0.611603 -0.138456,-0.810891 -0.558289,-0.810891 -0.347893,0 -0.508318,0.259253 -0.511933,0.827304 -0.0025,0.387238 0.06932,0.62667 0.224492,0.748724 0.137527,0.108179 0.411936,0.119877 0.594724,0.02535 z"
- id="path3227"
+ d="m 38.787461,38.290488 c -1.039138,1.851575 -2.42805,3.426908 -4.072502,4.609029 0.442312,1.546298 1.878767,2.686942 3.603022,2.686942 2.07403,0 3.757535,-1.642527 3.757535,-3.669969 0,-1.870656 -1.437304,-3.397874 -3.288055,-3.626002 z"
+ id="path3009-6"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d="m 13.333861,10.973929 0,-1.0586636 0.157674,0 0.157673,0 0,1.0586636 0,1.058663 -0.157673,0 -0.157674,0 0,-1.058663 z"
- id="path3229"
+ d="m 16.340734,38.277215 c -1.912727,0.170889 -3.41625,1.724653 -3.41625,3.639275 0,2.026612 1.680958,3.669969 3.755837,3.669969 1.752271,0 3.212497,-1.177974 3.626793,-2.764091 -1.598607,-1.174655 -2.950165,-2.728419 -3.96638,-4.545153 z"
+ id="path3011-6"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d="m 13.335306,9.4224208 c -0.03401,-0.063551 -0.03536,-0.1195255 -0.0043,-0.1775979 0.107644,-0.2011346 0.336943,-0.1203115 0.310785,0.1095452 -0.01206,0.1060051 -0.0396,0.1357548 -0.135983,0.1468893 -0.08514,0.00984 -0.135533,-0.013462 -0.170521,-0.078837 z"
- id="path3231"
+ d="m 20.375881,18.007772 c -0.291196,-1.744563 -1.828678,-3.078493 -3.69556,-3.078493 -2.074879,0 -3.755837,1.643356 -3.755837,3.669968 0,1.97601 1.601155,3.575399 3.603872,3.655037 1.006876,-1.694789 2.319381,-3.139051 3.847525,-4.246512 z"
+ id="path3013-4"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d="m 14.739943,12.028196 c -0.08967,-0.02671 -0.182942,-0.101218 -0.236342,-0.188797 -0.07856,-0.128853 -0.08823,-0.22968 -0.08838,-0.921782 l -1.68e-4,-0.777104 -0.157674,0 c -0.200927,0 -0.208018,-0.09496 -0.01395,-0.1868667 0.109989,-0.05209 0.161069,-0.1200886 0.217645,-0.2897326 0.05461,-0.1637579 0.09945,-0.2254289 0.171627,-0.2360637 0.09026,-0.0133 0.0977,0.0047 0.0977,0.2365099 l 0,0.2509055 0.270297,0 c 0.258284,0 0.270297,0.00501 0.270297,0.1126236 0,0.107618 -0.01201,0.112624 -0.270297,0.112624 l -0.270297,0 0,0.758859 c 0,0.868582 0.0153,0.907973 0.352681,0.907973 0.155976,0 0.187913,0.01486 0.187913,0.08744 0,0.04809 -0.01536,0.09693 -0.03413,0.108534 -0.08298,0.05129 -0.361449,0.06523 -0.496917,0.02488 z"
- id="path3233"
+ d="m 27.567493,15.62362 c 1.619832,0 3.164955,0.340948 4.599711,0.935742 0.629086,-0.892605 1.000085,-1.971862 1.000085,-3.138221 0,-3.058584 -2.537567,-5.5389654 -5.668563,-5.5389654 -3.130146,0 -5.667713,2.4803814 -5.667713,5.5389654 0,1.18461 0.383734,2.280457 1.032345,3.180529 1.463622,-0.62134 3.04525,-0.97805 4.704135,-0.97805 z"
+ id="path3015-9"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3017-5"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none">
+ <path
+ d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z"
+ id="path3019-0"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3021-4"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none">
+ <path
+ d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z"
+ id="path3023-8"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z"
+ id="path3025-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z"
+ id="path3027-1"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z"
+ id="path3029-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z"
+ id="path3031-2"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z"
+ id="path3033-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
</g>
+ <path
+ inkscape:connector-curvature="0"
+ d="m 37.826108,14.511339 2.437818,-2.366117 1.200984,0.84248 1.416085,1.200984 0.985882,1.272684 0.914181,1.487786 -2.366117,2.509519 -0.896257,-1.505711 -2.186866,-2.366117 -1.50571,-1.075508 z"
+ id="path3255"
+ style="fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:1px;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 35.137339,17.271808 2.294417,-2.079315 1.200984,0.84248 1.416085,1.200984 0.985882,1.272684 0.914181,1.487786 -2.079315,1.864214 -0.967957,-1.147208 -2.330267,-2.222716 -1.43401,-1.218909 z"
+ id="path3253"
+ style="fill:#000000;stroke:#ffffff;stroke-width:1px;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 15.683049,39.966575 0.891754,-3.80169 18.820708,-18.21056 -0.469344,-0.680549 2.252852,-2.135517 5.115854,5.115853 -2.229385,2.135517 -0.774419,-0.539747 -19.05538,18.022823 -3.70782,0.657082 -0.84482,-0.563212 z"
+ id="path2822"
+ style="fill:#000000;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 35.742233,18.517538 3.660886,3.473148"
+ id="path3596"
+ style="fill:#000000;stroke:#ffffff;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 13.195524,43.064247 2.769132,-2.816066"
+ id="path3598"
+ style="fill:#000000;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 16.950279,36.446491 c 0,0 1.594197,0.393866 2.158983,0.93869 0.574138,0.553844 1.032558,2.158984 1.032558,2.158984"
+ id="path3600"
+ style="fill:#000000;stroke:#ffffff;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
+ <path
+ style="fill:#ffffff"
+ d="M 20.447395,36.942513 C 20.27718,36.645931 19.883837,36.24876 19.573299,36.059911 l -0.564614,-0.343363 8.07,-7.818797 c 4.438499,-4.300338 8.135227,-7.818797 8.214949,-7.818797 0.07972,0 0.552,0.413263 1.049504,0.918363 l 0.904554,0.918362 -0.544779,0.523798 c -0.299628,0.288088 -3.721029,3.517184 -7.603112,7.175768 -3.882083,3.658584 -7.347366,6.925242 -7.700629,7.25924 l -0.642296,0.607268 -0.309481,-0.53924 z"
+ id="path2990"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff"
+ d="m 42.185184,17.903971 c -0.385066,-0.605404 -2.215315,-2.562189 -2.900953,-3.101512 l -0.446583,-0.351282 0.773579,-0.759211 0.773579,-0.75921 1.103351,0.892762 c 0.606843,0.49102 1.4187,1.350636 1.804126,1.910257 l 0.700775,1.017495 -0.368509,0.517008 c -0.202679,0.284355 -0.532115,0.664852 -0.732079,0.845549 -0.352751,0.318761 -0.373799,0.312457 -0.707286,-0.211856 l 0,0 z"
+ id="path2992"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff"
+ d="m 38.342157,19.094186 c -1.333982,-1.264073 -1.591222,-1.592584 -1.400927,-1.789073 0.190815,-0.197026 0.522406,0.04863 1.828095,1.354317 1.122173,1.122174 1.537468,1.652532 1.400927,1.789073 -0.136541,0.136541 -0.678467,-0.264937 -1.828095,-1.354317 l 0,0 z"
+ id="path2994"
+ inkscape:connector-curvature="0" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+ x="2.4431341"
+ y="12.158955"
+ id="text3002"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3004"
+ x="2.4431341"
+ y="12.158955">Left</tspan></text>
</svg>
diff --git a/icons/mirror.svg b/icons/mirror.svg
index 4a90bf0..da31f24 100644
--- a/icons/mirror.svg
+++ b/icons/mirror.svg
@@ -9,108 +9,167 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16px"
- height="16px"
- id="svg3043"
- version="1.1"
+ version="1.0"
+ width="45"
+ height="45"
+ viewBox="0 0 55 55"
+ id="svg2"
+ xml:space="preserve"
inkscape:version="0.48.0 r9654"
- sodipodi:docname="mirror.svg">
- <defs
- id="defs3045" />
- <sodipodi:namedview
- id="base"
+ sodipodi:docname="mirror.svg"><metadata
+ id="metadata24"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
inkscape:pageshadow="2"
- inkscape:zoom="22.197802"
- inkscape:cx="7.7888027"
- inkscape:cy="7.1205451"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
inkscape:window-width="1366"
inkscape:window-height="701"
+ id="namedview22"
+ showgrid="false"
+ inkscape:zoom="6.6666667"
+ inkscape:cx="22.5"
+ inkscape:cy="22.5"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
- showguides="true"
- inkscape:guide-bbox="true" />
- <metadata
- id="metadata3048">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="1.9821782"
- y="5.5485148"
- id="text3297"
- sodipodi:linespacing="125%"><tspan
- sodipodi:role="line"
- id="tspan3299" /></text>
- <text
- xml:space="preserve"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="13.740099"
- y="14.423267"
- id="text3305"
- sodipodi:linespacing="125%"><tspan
- sodipodi:role="line"
- id="tspan3307" /></text>
- <text
- xml:space="preserve"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="0.67574257"
- y="14.918812"
- id="text3309"
- sodipodi:linespacing="125%"><tspan
- sodipodi:role="line"
- id="tspan3311" /></text>
- <text
- xml:space="preserve"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="6.3519802"
- y="14.243069"
- id="text3313"
- sodipodi:linespacing="125%"><tspan
- sodipodi:role="line"
- id="tspan3315" /></text>
- <text
- xml:space="preserve"
- style="font-size:14.17995739px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.5153806"
- y="13.443896"
- id="text3336"
- sodipodi:linespacing="125%"
- transform="scale(1.0249348,0.97567183)"><tspan
- sodipodi:role="line"
- id="tspan3338"
- x="1.5153806"
- y="13.443896">M</tspan></text>
- <path
- style="fill:none;stroke:#000000;stroke-width:0.8782956px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 7.7860733,3.264443 C 7.8911545,13.872024 7.8911545,13.842227 7.8911545,13.842227"
- id="path3340"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#f5f5f5"
- d="m 7.491476,13.630417 c 0,-0.342406 -0.043788,-0.507299 -0.1347148,-0.507299 -0.063046,0 -0.3862303,-0.847068 -1.6499381,-4.3244936 C 4.7046661,6.0409247 4.1137112,4.4740365 4.0757344,4.4738717 c -0.045223,-1.963e-4 -0.053116,0.056656 -0.032802,0.2362515 0.082817,0.7321783 0.1140548,2.1216682 0.1144442,5.0905941 l 4.358e-4,3.3224007 -0.5856436,0 -0.5856436,0 0,-4.9329205 0,-4.9329209 0.957302,9.29e-5 0.957302,9.29e-5 1.2353374,3.4124071 c 0.6794355,1.8768241 1.2516916,3.4428155 1.2716802,3.4799815 0.034077,0.06336 0.02195,-2.1392938 -0.029824,-5.4172031 l -0.022592,-1.4303218 0.4282686,0 0.4282686,0 0.0065,1.3402228 c 0.00358,0.7371226 0.018779,2.3132921 0.033787,3.5025991 l 0.027287,2.162376 1.2839109,-3.524715 1.2839108,-3.5247152 0.957302,-4.086e-4 0.957302,-4.086e-4 0,4.9329209 0,4.9329205 -0.63457,0 -0.63457,0 0.02519,-4.0657176 c 0.01385,-2.2361448 0.03788,-4.1846438 0.0534,-4.3299977 0.02248,-0.2105865 0.01586,-0.2602314 -0.03257,-0.2443529 -0.03365,0.011033 -0.767967,1.9386419 -1.6451989,4.3187352 -1.560773,4.234666 -1.5844677,4.304018 -1.5879951,4.647942 l -0.00358,0.349134 -0.1964353,0 c -0.108039,0 -0.2904895,0.01289 -0.4054455,0.02865 l -0.2090103,0.02865 0,-0.22574 z"
- id="path3552"
- inkscape:connector-curvature="0" />
- </g>
-</svg>
+ inkscape:current-layer="svg2" /><defs
+ id="defs12">
+
+</defs><path
+ d=""
+ id="path2385"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:1.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path
+ d="m 27.819727,29.058334 c 0,9.643659 -7.243168,17.46139 -16.178057,17.46139 -8.9348965,0 -16.17806,-7.817731 -16.17806,-17.46139 0,-9.643661 7.2431635,-17.461392 16.17806,-17.461392 8.934889,0 16.178057,7.817731 16.178057,17.461392 l 0,0 z"
+ id="path2387"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:2.90499687;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 60.434689,28.691668 c 0,9.734763 -7.358068,17.626349 -16.434686,17.626349 -9.07663,0 -16.434687,-7.891586 -16.434687,-17.626349 0,-9.734766 7.358057,-17.626351 16.434687,-17.626351 9.076618,0 16.434686,7.891585 16.434686,17.626351 l 0,0 z"
+ id="path2387-6"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:2.94174433;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><g
+ transform="matrix(-0.01659623,-1.0372435,0.6831081,-0.02520003,24.251867,58.436695)"
+ id="g2937"><path
+ d="m 27.567493,45.252146 c -0.46948,0 -0.933016,-0.02903 -1.389761,-0.08296 l 1.178368,1.948634 1.161389,-1.918769 c -0.314968,0.02489 -0.629086,0.05309 -0.949996,0.05309 z"
+ id="path3003"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 38.317981,14.929279 c -1.837168,0 -3.360217,1.289964 -3.68707,2.992219 1.578232,1.115757 2.934884,2.584076 3.968928,4.320343 1.939893,-0.142684 3.475677,-1.709721 3.475677,-3.641764 0,-2.027442 -1.682656,-3.670798 -3.757535,-3.670798 z"
+ id="path3007"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 38.787461,38.290488 c -1.039138,1.851575 -2.42805,3.426908 -4.072502,4.609029 0.442312,1.546298 1.878767,2.686942 3.603022,2.686942 2.07403,0 3.757535,-1.642527 3.757535,-3.669969 0,-1.870656 -1.437304,-3.397874 -3.288055,-3.626002 z"
+ id="path3009"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 16.340734,38.277215 c -1.912727,0.170889 -3.41625,1.724653 -3.41625,3.639275 0,2.026612 1.680958,3.669969 3.755837,3.669969 1.752271,0 3.212497,-1.177974 3.626793,-2.764091 -1.598607,-1.174655 -2.950165,-2.728419 -3.96638,-4.545153 z"
+ id="path3011"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 20.375881,18.007772 c -0.291196,-1.744563 -1.828678,-3.078493 -3.69556,-3.078493 -2.074879,0 -3.755837,1.643356 -3.755837,3.669968 0,1.97601 1.601155,3.575399 3.603872,3.655037 1.006876,-1.694789 2.319381,-3.139051 3.847525,-4.246512 z"
+ id="path3013"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 27.567493,15.62362 c 1.619832,0 3.164955,0.340948 4.599711,0.935742 0.629086,-0.892605 1.000085,-1.971862 1.000085,-3.138221 0,-3.058584 -2.537567,-5.5389654 -5.668563,-5.5389654 -3.130146,0 -5.667713,2.4803814 -5.667713,5.5389654 0,1.18461 0.383734,2.280457 1.032345,3.180529 1.463622,-0.62134 3.04525,-0.97805 4.704135,-0.97805 z"
+ id="path3015"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3017"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z"
+ id="path3019"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /></g><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3021"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z"
+ id="path3023"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z"
+ id="path3025"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z"
+ id="path3027"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z"
+ id="path3029"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z"
+ id="path3031"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z"
+ id="path3033"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /></g></g><g
+ transform="matrix(-0.01612121,0.97919215,-0.75560071,-0.00584454,34.917446,2.2157285)"
+ id="g2937-8"><path
+ d="m 27.567493,45.252146 c -0.46948,0 -0.933016,-0.02903 -1.389761,-0.08296 l 1.178368,1.948634 1.161389,-1.918769 c -0.314968,0.02489 -0.629086,0.05309 -0.949996,0.05309 z"
+ id="path3003-9"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 38.317981,14.929279 c -1.837168,0 -3.360217,1.289964 -3.68707,2.992219 1.578232,1.115757 2.934884,2.584076 3.968928,4.320343 1.939893,-0.142684 3.475677,-1.709721 3.475677,-3.641764 0,-2.027442 -1.682656,-3.670798 -3.757535,-3.670798 z"
+ id="path3007-2"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 38.787461,38.290488 c -1.039138,1.851575 -2.42805,3.426908 -4.072502,4.609029 0.442312,1.546298 1.878767,2.686942 3.603022,2.686942 2.07403,0 3.757535,-1.642527 3.757535,-3.669969 0,-1.870656 -1.437304,-3.397874 -3.288055,-3.626002 z"
+ id="path3009-6"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 16.340734,38.277215 c -1.912727,0.170889 -3.41625,1.724653 -3.41625,3.639275 0,2.026612 1.680958,3.669969 3.755837,3.669969 1.752271,0 3.212497,-1.177974 3.626793,-2.764091 -1.598607,-1.174655 -2.950165,-2.728419 -3.96638,-4.545153 z"
+ id="path3011-6"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 20.375881,18.007772 c -0.291196,-1.744563 -1.828678,-3.078493 -3.69556,-3.078493 -2.074879,0 -3.755837,1.643356 -3.755837,3.669968 0,1.97601 1.601155,3.575399 3.603872,3.655037 1.006876,-1.694789 2.319381,-3.139051 3.847525,-4.246512 z"
+ id="path3013-4"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 27.567493,15.62362 c 1.619832,0 3.164955,0.340948 4.599711,0.935742 0.629086,-0.892605 1.000085,-1.971862 1.000085,-3.138221 0,-3.058584 -2.537567,-5.5389654 -5.668563,-5.5389654 -3.130146,0 -5.667713,2.4803814 -5.667713,5.5389654 0,1.18461 0.383734,2.280457 1.032345,3.180529 1.463622,-0.62134 3.04525,-0.97805 4.704135,-0.97805 z"
+ id="path3015-9"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3017-5"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z"
+ id="path3019-0"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /></g><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3021-4"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z"
+ id="path3023-8"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z"
+ id="path3025-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z"
+ id="path3027-1"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z"
+ id="path3029-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z"
+ id="path3031-2"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z"
+ id="path3033-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /></g></g></svg> \ No newline at end of file
diff --git a/icons/offset.svg b/icons/offset.svg
index 87f89ed..fa5804c 100644
--- a/icons/offset.svg
+++ b/icons/offset.svg
@@ -9,76 +9,295 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16px"
- height="16px"
- id="svg2985"
- version="1.1"
+ version="1.0"
+ width="45"
+ height="45"
+ viewBox="0 0 55 55"
+ id="svg2"
+ xml:space="preserve"
inkscape:version="0.48.0 r9654"
- sodipodi:docname="offset.svg">
- <defs
- id="defs2987" />
- <sodipodi:namedview
- id="base"
+ sodipodi:docname="offset.svg"><metadata
+ id="metadata24"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
inkscape:pageshadow="2"
- inkscape:zoom="22.197802"
- inkscape:cx="8"
- inkscape:cy="5.4681565"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
inkscape:window-width="1366"
inkscape:window-height="701"
+ id="namedview22"
+ showgrid="false"
+ inkscape:zoom="6.6666667"
+ inkscape:cx="22.5"
+ inkscape:cy="22.5"
inkscape:window-x="0"
inkscape:window-y="0"
- inkscape:window-maximized="1" />
- <metadata
- id="metadata2990">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <text
- xml:space="preserve"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="4.1896038"
- y="14.243069"
- id="text3011"
- sodipodi:linespacing="125%"><tspan
- sodipodi:role="line"
- id="tspan3013"
- x="4.1896038"
- y="14.243069" /></text>
- <text
- xml:space="preserve"
- style="font-size:15.23624706px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="4.0866394"
- y="11.582109"
- id="text3015"
- sodipodi:linespacing="125%"
- transform="scale(0.97870254,1.0217609)"><tspan
- sodipodi:role="line"
- id="tspan3017"
- x="4.0866394"
- y="11.582109">o</tspan></text>
- <path
- style="fill:#f5f5f5"
- d="M 7.8170503,11.934786 C 6.616538,11.74889 5.6744154,10.978525 5.2262043,9.8162749 4.93377,9.0579674 4.8894445,8.7748889 4.8882043,7.6576851 4.887016,6.5871402 4.9097066,6.4009086 5.1214808,5.7430811 5.5195175,4.5066731 6.2992968,3.7420527 7.4414155,3.4682461 7.9460934,3.3472567 8.6890871,3.3459072 9.1552563,3.4651332 10.77394,3.8791227 11.757129,5.4575136 11.757129,7.6421237 c 0,2.2553998 -0.928829,3.7917423 -2.5417799,4.2042653 -0.4022664,0.102883 -1.0431194,0.143396 -1.3982988,0.0884 l 0,0 z M 8.8379559,10.805503 C 9.8058806,10.59995 10.27471,9.8418923 10.410845,8.2622701 10.500866,7.2177429 10.359527,6.1312969 10.048967,5.4805781 9.6892064,4.7267666 8.8876304,4.3534742 7.9288084,4.4932239 6.7756252,4.661302 6.2581551,5.5006428 6.18616,7.3198138 c -0.069034,1.744342 0.3205647,2.9224892 1.0943519,3.3093242 0.4291195,0.214528 1.0478242,0.28459 1.557444,0.176365 l 0,0 z"
- id="path3032"
- inkscape:connector-curvature="0" />
- </g>
-</svg>
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" /><defs
+ id="defs12">
+
+</defs><path
+ d=""
+ id="path2385"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:1.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path
+ d="m 26.923202,15.033334 c 0,6.465341 -5.815763,11.706536 -12.989869,11.706536 -7.1741065,0 -12.98986848,-5.241195 -12.98986848,-11.706536 0,-6.4653414 5.81576198,-11.7065367 12.98986848,-11.7065367 7.174106,0 12.989869,5.2411953 12.989869,11.7065367 l 0,0 z"
+ id="path2387"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:2.13137388;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><g
+ transform="matrix(0.62032316,0.04879304,-0.03631938,0.54470389,-1.8432578,-2.0491548)"
+ id="g2937-8"><path
+ d="m 27.567493,45.252146 c -0.46948,0 -0.933016,-0.02903 -1.389761,-0.08296 l 1.178368,1.948634 1.161389,-1.918769 c -0.314968,0.02489 -0.629086,0.05309 -0.949996,0.05309 z"
+ id="path3003-9"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 38.317981,14.929279 c -1.837168,0 -3.360217,1.289964 -3.68707,2.992219 1.578232,1.115757 2.934884,2.584076 3.968928,4.320343 1.939893,-0.142684 3.475677,-1.709721 3.475677,-3.641764 0,-2.027442 -1.682656,-3.670798 -3.757535,-3.670798 z"
+ id="path3007-2"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 38.787461,38.290488 c -1.039138,1.851575 -2.42805,3.426908 -4.072502,4.609029 0.442312,1.546298 1.878767,2.686942 3.603022,2.686942 2.07403,0 3.757535,-1.642527 3.757535,-3.669969 0,-1.870656 -1.437304,-3.397874 -3.288055,-3.626002 z"
+ id="path3009-6"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 16.340734,38.277215 c -1.912727,0.170889 -3.41625,1.724653 -3.41625,3.639275 0,2.026612 1.680958,3.669969 3.755837,3.669969 1.752271,0 3.212497,-1.177974 3.626793,-2.764091 -1.598607,-1.174655 -2.950165,-2.728419 -3.96638,-4.545153 z"
+ id="path3011-6"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 20.375881,18.007772 c -0.291196,-1.744563 -1.828678,-3.078493 -3.69556,-3.078493 -2.074879,0 -3.755837,1.643356 -3.755837,3.669968 0,1.97601 1.601155,3.575399 3.603872,3.655037 1.006876,-1.694789 2.319381,-3.139051 3.847525,-4.246512 z"
+ id="path3013-4"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 27.567493,15.62362 c 1.619832,0 3.164955,0.340948 4.599711,0.935742 0.629086,-0.892605 1.000085,-1.971862 1.000085,-3.138221 0,-3.058584 -2.537567,-5.5389654 -5.668563,-5.5389654 -3.130146,0 -5.667713,2.4803814 -5.667713,5.5389654 0,1.18461 0.383734,2.280457 1.032345,3.180529 1.463622,-0.62134 3.04525,-0.97805 4.704135,-0.97805 z"
+ id="path3015-9"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3017-5"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z"
+ id="path3019-0"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /></g><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3021-4"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z"
+ id="path3023-8"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z"
+ id="path3025-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z"
+ id="path3027-1"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z"
+ id="path3029-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z"
+ id="path3031-2"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z"
+ id="path3033-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /></g></g><path
+ d="m 54.056536,14.483333 c 0,6.465342 -5.815764,11.706537 -12.989869,11.706537 -7.174107,0 -12.989869,-5.241195 -12.989869,-11.706537 0,-6.4653406 5.815762,-11.706536 12.989869,-11.706536 7.174105,0 12.989869,5.2411954 12.989869,11.706536 l 0,0 z"
+ id="path2387-6"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:2.13137388;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><g
+ transform="matrix(0.6327059,5.5784179e-4,0.0050677,0.5067211,23.513916,0.138915)"
+ id="g2937"><path
+ d="m 27.567493,45.252146 c -0.46948,0 -0.933016,-0.02903 -1.389761,-0.08296 l 1.178368,1.948634 1.161389,-1.918769 c -0.314968,0.02489 -0.629086,0.05309 -0.949996,0.05309 z"
+ id="path3003"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 38.317981,14.929279 c -1.837168,0 -3.360217,1.289964 -3.68707,2.992219 1.578232,1.115757 2.934884,2.584076 3.968928,4.320343 1.939893,-0.142684 3.475677,-1.709721 3.475677,-3.641764 0,-2.027442 -1.682656,-3.670798 -3.757535,-3.670798 z"
+ id="path3007"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 38.787461,38.290488 c -1.039138,1.851575 -2.42805,3.426908 -4.072502,4.609029 0.442312,1.546298 1.878767,2.686942 3.603022,2.686942 2.07403,0 3.757535,-1.642527 3.757535,-3.669969 0,-1.870656 -1.437304,-3.397874 -3.288055,-3.626002 z"
+ id="path3009"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 16.340734,38.277215 c -1.912727,0.170889 -3.41625,1.724653 -3.41625,3.639275 0,2.026612 1.680958,3.669969 3.755837,3.669969 1.752271,0 3.212497,-1.177974 3.626793,-2.764091 -1.598607,-1.174655 -2.950165,-2.728419 -3.96638,-4.545153 z"
+ id="path3011"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 20.375881,18.007772 c -0.291196,-1.744563 -1.828678,-3.078493 -3.69556,-3.078493 -2.074879,0 -3.755837,1.643356 -3.755837,3.669968 0,1.97601 1.601155,3.575399 3.603872,3.655037 1.006876,-1.694789 2.319381,-3.139051 3.847525,-4.246512 z"
+ id="path3013"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 27.567493,15.62362 c 1.619832,0 3.164955,0.340948 4.599711,0.935742 0.629086,-0.892605 1.000085,-1.971862 1.000085,-3.138221 0,-3.058584 -2.537567,-5.5389654 -5.668563,-5.5389654 -3.130146,0 -5.667713,2.4803814 -5.667713,5.5389654 0,1.18461 0.383734,2.280457 1.032345,3.180529 1.463622,-0.62134 3.04525,-0.97805 4.704135,-0.97805 z"
+ id="path3015"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3017"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z"
+ id="path3019"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /></g><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3021"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z"
+ id="path3023"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z"
+ id="path3025"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z"
+ id="path3027"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z"
+ id="path3029"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z"
+ id="path3031"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z"
+ id="path3033"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /></g></g><path
+ d="m 27.839869,41.066666 c 0,6.465342 -5.815764,11.706537 -12.989869,11.706537 -7.1741075,0 -12.9898695,-5.241195 -12.9898695,-11.706537 0,-6.465341 5.815762,-11.706536 12.9898695,-11.706536 7.174105,0 12.989869,5.241195 12.989869,11.706536 l 0,0 z"
+ id="path2387-8"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:2.13137388;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><g
+ transform="matrix(0.62032316,0.04879304,-0.03631938,0.54470389,-1.4765912,23.984178)"
+ id="g2937-8-0"><path
+ d="m 27.567493,45.252146 c -0.46948,0 -0.933016,-0.02903 -1.389761,-0.08296 l 1.178368,1.948634 1.161389,-1.918769 c -0.314968,0.02489 -0.629086,0.05309 -0.949996,0.05309 z"
+ id="path3003-9-3"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 38.317981,14.929279 c -1.837168,0 -3.360217,1.289964 -3.68707,2.992219 1.578232,1.115757 2.934884,2.584076 3.968928,4.320343 1.939893,-0.142684 3.475677,-1.709721 3.475677,-3.641764 0,-2.027442 -1.682656,-3.670798 -3.757535,-3.670798 z"
+ id="path3007-2-0"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 38.787461,38.290488 c -1.039138,1.851575 -2.42805,3.426908 -4.072502,4.609029 0.442312,1.546298 1.878767,2.686942 3.603022,2.686942 2.07403,0 3.757535,-1.642527 3.757535,-3.669969 0,-1.870656 -1.437304,-3.397874 -3.288055,-3.626002 z"
+ id="path3009-6-4"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 16.340734,38.277215 c -1.912727,0.170889 -3.41625,1.724653 -3.41625,3.639275 0,2.026612 1.680958,3.669969 3.755837,3.669969 1.752271,0 3.212497,-1.177974 3.626793,-2.764091 -1.598607,-1.174655 -2.950165,-2.728419 -3.96638,-4.545153 z"
+ id="path3011-6-4"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 20.375881,18.007772 c -0.291196,-1.744563 -1.828678,-3.078493 -3.69556,-3.078493 -2.074879,0 -3.755837,1.643356 -3.755837,3.669968 0,1.97601 1.601155,3.575399 3.603872,3.655037 1.006876,-1.694789 2.319381,-3.139051 3.847525,-4.246512 z"
+ id="path3013-4-4"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 27.567493,15.62362 c 1.619832,0 3.164955,0.340948 4.599711,0.935742 0.629086,-0.892605 1.000085,-1.971862 1.000085,-3.138221 0,-3.058584 -2.537567,-5.5389654 -5.668563,-5.5389654 -3.130146,0 -5.667713,2.4803814 -5.667713,5.5389654 0,1.18461 0.383734,2.280457 1.032345,3.180529 1.463622,-0.62134 3.04525,-0.97805 4.704135,-0.97805 z"
+ id="path3015-9-4"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3017-5-7"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z"
+ id="path3019-0-6"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /></g><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3021-4-3"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z"
+ id="path3023-8-1"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z"
+ id="path3025-7-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z"
+ id="path3027-1-5"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z"
+ id="path3029-7-9"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z"
+ id="path3031-2-6"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z"
+ id="path3033-7-2"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /></g></g><path
+ d="m 54.056536,40.333333 c 0,6.465342 -5.815764,11.706537 -12.989868,11.706537 -7.174108,0 -12.98987,-5.241195 -12.98987,-11.706537 0,-6.465341 5.815762,-11.706536 12.98987,-11.706536 7.174104,0 12.989868,5.241195 12.989868,11.706536 l 0,0 z"
+ id="path2387-8-9"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:2.13137388;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><g
+ transform="matrix(0.6327059,5.5784179e-4,0.0050677,0.5067211,23.513916,25.438915)"
+ id="g2937-88"><path
+ d="m 27.567493,45.252146 c -0.46948,0 -0.933016,-0.02903 -1.389761,-0.08296 l 1.178368,1.948634 1.161389,-1.918769 c -0.314968,0.02489 -0.629086,0.05309 -0.949996,0.05309 z"
+ id="path3003-5"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 38.317981,14.929279 c -1.837168,0 -3.360217,1.289964 -3.68707,2.992219 1.578232,1.115757 2.934884,2.584076 3.968928,4.320343 1.939893,-0.142684 3.475677,-1.709721 3.475677,-3.641764 0,-2.027442 -1.682656,-3.670798 -3.757535,-3.670798 z"
+ id="path3007-0"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 38.787461,38.290488 c -1.039138,1.851575 -2.42805,3.426908 -4.072502,4.609029 0.442312,1.546298 1.878767,2.686942 3.603022,2.686942 2.07403,0 3.757535,-1.642527 3.757535,-3.669969 0,-1.870656 -1.437304,-3.397874 -3.288055,-3.626002 z"
+ id="path3009-9"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 16.340734,38.277215 c -1.912727,0.170889 -3.41625,1.724653 -3.41625,3.639275 0,2.026612 1.680958,3.669969 3.755837,3.669969 1.752271,0 3.212497,-1.177974 3.626793,-2.764091 -1.598607,-1.174655 -2.950165,-2.728419 -3.96638,-4.545153 z"
+ id="path3011-63"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 20.375881,18.007772 c -0.291196,-1.744563 -1.828678,-3.078493 -3.69556,-3.078493 -2.074879,0 -3.755837,1.643356 -3.755837,3.669968 0,1.97601 1.601155,3.575399 3.603872,3.655037 1.006876,-1.694789 2.319381,-3.139051 3.847525,-4.246512 z"
+ id="path3013-8"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 27.567493,15.62362 c 1.619832,0 3.164955,0.340948 4.599711,0.935742 0.629086,-0.892605 1.000085,-1.971862 1.000085,-3.138221 0,-3.058584 -2.537567,-5.5389654 -5.668563,-5.5389654 -3.130146,0 -5.667713,2.4803814 -5.667713,5.5389654 0,1.18461 0.383734,2.280457 1.032345,3.180529 1.463622,-0.62134 3.04525,-0.97805 4.704135,-0.97805 z"
+ id="path3015-5"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3017-6"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z"
+ id="path3019-1"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /></g><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3021-1"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z"
+ id="path3023-5"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z"
+ id="path3025-9"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z"
+ id="path3027-8"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z"
+ id="path3029-4"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z"
+ id="path3031-8"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /><path
+ d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z"
+ id="path3033-1"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" /></g></g></svg> \ No newline at end of file
diff --git a/icons/original.svg b/icons/original.svg
index 78c5be8..074e2a2 100644
--- a/icons/original.svg
+++ b/icons/original.svg
@@ -9,59 +9,90 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16px"
- height="16px"
- id="svg3055"
- version="1.1"
+ version="1.0"
+ width="45"
+ height="45"
+ viewBox="0 0 55 55"
+ id="svg2"
+ xml:space="preserve"
inkscape:version="0.48.0 r9654"
- sodipodi:docname="original.svg">
- <defs
- id="defs3057" />
- <sodipodi:namedview
- id="base"
+ sodipodi:docname="run-slowon.svg"><metadata
+ id="metadata24"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
inkscape:pageshadow="2"
- inkscape:zoom="22.197802"
- inkscape:cx="8"
- inkscape:cy="8"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
inkscape:window-width="1366"
inkscape:window-height="701"
+ id="namedview22"
+ showgrid="false"
+ inkscape:zoom="6.6666667"
+ inkscape:cx="22.5"
+ inkscape:cy="22.5"
inkscape:window-x="0"
inkscape:window-y="0"
- inkscape:window-maximized="1" />
- <metadata
- id="metadata3060">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <text
- xml:space="preserve"
- style="font-size:11.73679543000000081px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="4.3141747"
- y="11.85775"
- id="text3402"
- sodipodi:linespacing="125%"
- transform="scale(0.95574243,1.046307)"><tspan
- sodipodi:role="line"
- id="tspan3404"
- x="4.3141747"
- y="11.85775">U</tspan></text>
- </g>
-</svg>
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" /><defs
+ id="defs12">
+
+</defs><path
+ d="m 36.852226,15.69838 c 0,5.964452 -5.159148,10.799595 -11.523279,10.799595 -6.364131,0 -11.523279,-4.835143 -11.523279,-10.799595 0,-5.9644517 5.159148,-10.7995952 11.523279,-10.7995952 6.364131,0 11.523279,4.8351435 11.523279,10.7995952 l 0,0 z"
+ transform="matrix(2.1478261,0,0,2.2917526,-26.902174,-8.4768043)"
+ id="path2387"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:1.92812335;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none" /><path
+ d=""
+ id="path2385"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:1.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><g
+ transform="matrix(0,1.2222222,-1.2222222,0,62.905112,-6.1105186)"
+ id="g2937"><path
+ d="m 27.567493,45.252146 c -0.46948,0 -0.933016,-0.02903 -1.389761,-0.08296 l 1.178368,1.948634 1.161389,-1.918769 c -0.314968,0.02489 -0.629086,0.05309 -0.949996,0.05309 z"
+ id="path3003"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path
+ d="m 38.317981,14.929279 c -1.837168,0 -3.360217,1.289964 -3.68707,2.992219 1.578232,1.115757 2.934884,2.584076 3.968928,4.320343 1.939893,-0.142684 3.475677,-1.709721 3.475677,-3.641764 0,-2.027442 -1.682656,-3.670798 -3.757535,-3.670798 z"
+ id="path3007"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path
+ d="m 38.787461,38.290488 c -1.039138,1.851575 -2.42805,3.426908 -4.072502,4.609029 0.442312,1.546298 1.878767,2.686942 3.603022,2.686942 2.07403,0 3.757535,-1.642527 3.757535,-3.669969 0,-1.870656 -1.437304,-3.397874 -3.288055,-3.626002 z"
+ id="path3009"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path
+ d="m 16.340734,38.277215 c -1.912727,0.170889 -3.41625,1.724653 -3.41625,3.639275 0,2.026612 1.680958,3.669969 3.755837,3.669969 1.752271,0 3.212497,-1.177974 3.626793,-2.764091 -1.598607,-1.174655 -2.950165,-2.728419 -3.96638,-4.545153 z"
+ id="path3011"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path
+ d="m 20.375881,18.007772 c -0.291196,-1.744563 -1.828678,-3.078493 -3.69556,-3.078493 -2.074879,0 -3.755837,1.643356 -3.755837,3.669968 0,1.97601 1.601155,3.575399 3.603872,3.655037 1.006876,-1.694789 2.319381,-3.139051 3.847525,-4.246512 z"
+ id="path3013"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path
+ d="m 27.567493,15.62362 c 1.619832,0 3.164955,0.340948 4.599711,0.935742 0.629086,-0.892605 1.000085,-1.971862 1.000085,-3.138221 0,-3.058584 -2.537567,-5.5389654 -5.668563,-5.5389654 -3.130146,0 -5.667713,2.4803814 -5.667713,5.5389654 0,1.18461 0.383734,2.280457 1.032345,3.180529 1.463622,-0.62134 3.04525,-0.97805 4.704135,-0.97805 z"
+ id="path3015"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3017"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z"
+ id="path3019"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3021"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z"
+ id="path3023"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path
+ d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z"
+ id="path3025"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path
+ d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z"
+ id="path3027"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path
+ d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z"
+ id="path3029"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path
+ d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z"
+ id="path3031"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path
+ d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z"
+ id="path3033"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></svg> \ No newline at end of file
diff --git a/icons/right_bottom.svg b/icons/right_bottom.svg
index 1131ac9..16f7cc5 100644
--- a/icons/right_bottom.svg
+++ b/icons/right_bottom.svg
@@ -9,35 +9,14 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16px"
- height="16px"
- id="svg3017"
- version="1.1"
+ version="1.0"
+ width="55"
+ height="55"
+ id="svg2"
inkscape:version="0.48.0 r9654"
sodipodi:docname="right_bottom.svg">
- <defs
- id="defs3019" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="22.197802"
- inkscape:cx="8"
- inkscape:cy="10.328398"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
- inkscape:window-width="1366"
- inkscape:window-height="701"
- inkscape:window-x="0"
- inkscape:window-y="0"
- inkscape:window-maximized="1" />
<metadata
- id="metadata3022">
+ id="metadata13">
<rdf:RDF>
<cc:Work
rdf:about="">
@@ -48,233 +27,200 @@
</cc:Work>
</rdf:RDF>
</metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1366"
+ inkscape:window-height="701"
+ id="namedview11"
+ showgrid="false"
+ inkscape:zoom="5.4545455"
+ inkscape:cx="27.5"
+ inkscape:cy="16.853243"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" />
+ <defs
+ id="defs5" />
+ <text
+ xml:space="preserve"
+ style="font-size:6px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+ x="3.3"
+ y="12.65"
+ id="text3004"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3006"
+ x="3.3"
+ y="12.65" /></text>
+ <text
+ xml:space="preserve"
+ style="font-size:6px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+ x="41.25"
+ y="11.183333"
+ id="text3144"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3146"
+ x="41.25"
+ y="11.183333" /></text>
+ <text
+ xml:space="preserve"
+ style="font-size:6px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+ x="2.5666666"
+ y="52.616669"
+ id="text3167"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3169"
+ x="2.5666666"
+ y="52.616669" /></text>
+ <path
+ d="m 48.083471,26.216668 c 0,10.889291 -9.133454,19.716803 -20.400137,19.716803 -11.266686,0 -20.4001378,-8.827512 -20.4001378,-19.716803 0,-10.88929 9.1334518,-19.7168061 20.4001378,-19.7168061 11.266683,0 20.400137,8.8275161 20.400137,19.7168061 l 0,0 z"
+ id="path2387"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:3.46639347;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
<g
- id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="1.4415842"
- y="15.279208"
- id="text3025"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3027"
- x="1.4415842"
- y="15.279208"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;writing-mode:lr-tb;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="3.3336635"
- y="8.7019796"
- id="text3029"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3031" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="3.1985149"
- y="11.314851"
- id="text3033"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3035" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="1.8920792"
- y="14.062871"
- id="text3056"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3058"
- x="1.8920792"
- y="14.062871"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;writing-mode:lr-tb;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans"> </tspan></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122%;letter-spacing:0px;word-spacing:0px;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.2163366"
- y="3.791584"
- id="text3117"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3119"
- x="1.2163366"
- y="3.791584" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="8.9198017"
- y="4.5123763"
- id="text3154"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- x="8.9198017"
- y="4.5123763"
- id="tspan3158" /><tspan
- sodipodi:role="line"
- x="8.9198017"
- y="14.272377"
- id="tspan3160" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="2.0722773"
- y="14.738614"
- id="text3162"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3164"
- x="2.0722773"
- y="14.738614" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.0361387"
- y="15.144059"
- id="text3166"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3168"
- x="1.0361387"
- y="15.144059" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="0.58564359"
- y="4.1069307"
- id="text3191"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3193" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.0811881"
- y="10.278713"
- id="text3216"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- x="1.0811881"
- y="10.278713"
- id="tspan3220" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.0811881"
- y="15.459406"
- id="text3224"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3226"
- x="1.0811881"
- y="15.459406" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.4415842"
- y="6.8099008"
- id="text3228"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3230"
- x="1.4415842"
- y="6.8099008" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="0.27029702"
- y="6.8099008"
- id="text3232"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3234"
- x="0.27029702"
- y="6.8099008">text edit</tspan></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="9.7757425"
- y="15.234158"
- id="text3255"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3257"
- x="9.7757425"
- y="15.234158">R-B</tspan></text>
- <path
- style="fill:#ffffff"
- d="M 0.9998435,6.8024538 C 0.91017723,6.775747 0.81690142,6.7012352 0.76350199,6.6136564 0.6849364,6.4848036 0.6752688,6.3839765 0.67511883,5.6918743 l -1.684e-4,-0.777104 -0.15767327,0 c -0.20450798,0 -0.20678618,-0.095041 -0.004589,-0.1914616 0.12121407,-0.057803 0.1688609,-0.1205011 0.228868,-0.3011655 0.0560095,-0.1686289 0.0983495,-0.228165 0.16226278,-0.228165 0.0747894,0 0.0864785,0.033491 0.0864785,0.2477723 l 0,0.2477723 0.27029703,0 c 0.2582838,0 0.270297,0.00501 0.270297,0.1126237 0,0.1076183 -0.012013,0.1126238 -0.270297,0.1126238 l -0.27029703,0 0,0.7588595 c 0,0.8685819 0.0153003,0.9079722 0.35268093,0.9079722 0.1559756,0 0.1879131,0.014861 0.1879131,0.08744 0,0.048092 -0.015359,0.096933 -0.03413,0.108534 -0.082981,0.051285 -0.3614494,0.065226 -0.4969173,0.024878 z"
- id="path3336"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 2.5531488,6.7885855 C 2.2891192,6.7163791 2.0544255,6.5002315 1.9537124,6.236518 1.8388849,5.9358466 1.8826174,5.3522224 2.0401126,5.0834771 2.3240392,4.598993 2.9171221,4.5202209 3.2947898,4.9168334 c 0.1610986,0.1691798 0.263329,0.4578123 0.263329,0.7434711 l 0,0.1104064 -0.6820176,0 -0.6820176,0 0.026866,0.2268396 c 0.053704,0.4534426 0.3428047,0.6417658 0.8416248,0.5482426 0.1362748,-0.02555 0.2832488,-0.060523 0.3266089,-0.077717 0.064326,-0.025508 0.078837,-0.00681 0.078837,0.1015753 0,0.1148629 -0.022859,0.1393871 -0.1689357,0.1812414 -0.302798,0.086759 -0.5253919,0.098006 -0.7459353,0.037693 l 0,0 z M 3.1977227,5.4080777 c 0,-0.1698534 -0.1072985,-0.3851335 -0.2227522,-0.4469224 -0.1459494,-0.07811 -0.4301392,-0.054802 -0.5579871,0.045763 -0.1038301,0.081673 -0.2093924,0.323967 -0.2100986,0.4822331 -1.858e-4,0.041652 0.1287567,0.056312 0.4952934,0.056312 l 0.4955445,0 0,-0.1373857 z"
- id="path3338"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 4.2369013,6.2617179 4.6021163,5.7165864 4.2600996,5.2030546 3.9180829,4.6895228 l 0.1712048,0 c 0.1673451,0 0.1767445,0.00914 0.4169239,0.4052906 C 4.6413571,5.3177232 4.7620668,5.49969 4.7744554,5.4991839 4.786844,5.4986779 4.9042885,5.3162972 5.0354432,5.0938934 5.2625701,4.7087458 5.2813088,4.6895228 5.4296264,4.6895228 c 0.085646,0 0.1557201,0.010812 0.1557201,0.024027 0,0.013214 -0.1434506,0.2378362 -0.3187793,0.4991592 -0.1753285,0.261323 -0.3079789,0.5032778 -0.2947785,0.5376775 0.0132,0.0344 0.1667872,0.2753646 0.341304,0.5354777 0.1745168,0.2601131 0.3173033,0.4837448 0.3173033,0.4969594 0,0.013215 -0.070111,0.024026 -0.1558024,0.024026 -0.1484334,0 -0.1681427,-0.020223 -0.416708,-0.4275671 C 4.9143876,6.1441205 4.7845492,5.9515339 4.7693558,5.9513121 4.7541624,5.9510903 4.6252122,6.1434956 4.4827998,6.3788792 4.2266091,6.8023195 4.2220044,6.8068495 4.0477773,6.8068495 l -0.176091,0 0.365215,-0.5451316 z"
- id="path3340"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 9.1169877,6.8025921 C 8.6876913,6.7015798 8.4234654,6.2989609 8.4234654,5.745825 c 0,-0.3581282 0.097634,-0.6309877 0.2999517,-0.8382781 0.5297235,-0.542744 1.3654209,-0.1182216 1.3666289,0.6942284 l 2.51e-4,0.1689356 -0.6757425,0 -0.6757426,0 0,0.1481277 c 0,0.08147 0.045613,0.2385805 0.1013614,0.3491337 0.1341402,0.2660084 0.3397027,0.3440888 0.7320544,0.278062 0.1486634,-0.025018 0.3057736,-0.059827 0.3491337,-0.077354 0.064463,-0.026057 0.078837,-0.00765 0.078837,0.1009709 0,0.1145403 -0.023269,0.1397547 -0.1689356,0.1830565 -0.2679836,0.079663 -0.5145374,0.096882 -0.7142747,0.049884 l 0,0 z M 9.729901,5.4080777 C 9.729901,5.2382243 9.6226025,5.0229442 9.5071488,4.9611553 9.2579802,4.8278043 8.9205372,4.9579619 8.8119701,5.2292978 8.6842446,5.5485152 8.6801676,5.5454634 9.2343564,5.5454634 l 0.4955446,0 0,-0.1373857 z"
- id="path3342"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 11.177017,6.806756 C 10.954583,6.7542393 10.805634,6.625006 10.679377,6.3749855 10.584704,6.1875088 10.56775,6.0915802 10.568603,5.7481862 c 0.0015,-0.6218861 0.191126,-0.9477891 0.618246,-1.0628004 0.225892,-0.060827 0.456978,-0.00187 0.633338,0.16157 0.06698,0.062075 0.130874,0.112864 0.141986,0.112864 0.01111,0 0.0202,-0.2635396 0.0202,-0.5856436 l 0,-0.5856435 0.157674,0 0.157673,0 0,1.5091584 0,1.5091584 -0.135149,0 c -0.109916,0 -0.135277,-0.018924 -0.135838,-0.1013614 -0.0014,-0.1988149 -0.06381,-0.2231121 -0.2022,-0.078663 -0.106728,0.1114004 -0.379271,0.2383256 -0.472853,0.2202111 -0.01239,-0.0024 -0.09099,-0.020524 -0.174666,-0.04028 z m 0.530954,-0.2906038 c 0.18785,-0.097141 0.25201,-0.299197 0.251007,-0.7904908 -0.0012,-0.6116031 -0.138456,-0.8108911 -0.55829,-0.8108911 -0.347892,0 -0.508317,0.2592534 -0.511932,0.8273036 -0.0025,0.3872383 0.06932,0.6266705 0.224491,0.7487247 0.137527,0.1081785 0.411936,0.1198768 0.594724,0.025354 z"
- id="path3344"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="m 13.018515,5.7481862 0,-1.0586634 0.157673,0 0.157673,0 0,1.0586634 0,1.0586633 -0.157673,0 -0.157673,0 0,-1.0586633 z"
- id="path3346"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="m 13.01996,4.1966781 c -0.03401,-0.063551 -0.03536,-0.1195254 -0.0043,-0.1775979 0.107644,-0.2011345 0.336943,-0.1203114 0.310786,0.1095453 -0.01206,0.1060051 -0.0396,0.1357548 -0.135983,0.1468893 -0.08514,0.00984 -0.135534,-0.013462 -0.170521,-0.078837 z"
- id="path3348"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 14.424596,6.8024538 C 14.33493,6.775747 14.241654,6.7012352 14.188255,6.6136564 14.109689,6.4848036 14.100021,6.3839765 14.099871,5.6918743 l -1.68e-4,-0.777104 -0.157673,0 c -0.200928,0 -0.208019,-0.094959 -0.01395,-0.1868666 0.10999,-0.05209 0.16107,-0.1200886 0.217646,-0.2897326 0.05461,-0.163758 0.09945,-0.2254289 0.171627,-0.2360637 0.09026,-0.0133 0.0977,0.0047 0.0977,0.2365099 l 0,0.2509055 0.270297,0 c 0.258283,0 0.270297,0.00501 0.270297,0.1126237 0,0.1076183 -0.01201,0.1126238 -0.270297,0.1126238 l -0.270297,0 0,0.7588595 c 0,0.8685819 0.0153,0.9079722 0.35268,0.9079722 0.155976,0 0.187914,0.014861 0.187914,0.08744 0,0.048092 -0.01536,0.096933 -0.03413,0.108534 -0.08298,0.051285 -0.361449,0.065226 -0.496917,0.024878 z"
- id="path3350"
- inkscape:connector-curvature="0" />
+ transform="matrix(0.9741959,0.08217998,-0.05703833,0.91742079,2.9067458,-2.5546158)"
+ id="g2937-8">
<path
- style="fill:#ffffff"
- d="m 10.180396,13.812048 0,-1.41906 0.349134,2.61e-4 c 0.896308,6.7e-4 1.257204,0.19691 1.306548,0.710446 0.03035,0.315873 -0.102239,0.599892 -0.344703,0.738379 -0.101226,0.05782 -0.184204,0.120137 -0.184394,0.138488 -1.91e-4,0.01835 0.161831,0.297285 0.360049,0.619852 0.198218,0.322567 0.360396,0.596433 0.360396,0.608589 0,0.01216 -0.07722,0.0221 -0.171609,0.0221 l -0.171608,0 -0.335199,-0.584163 -0.335198,-0.584163 -0.259035,-0.0015 -0.259034,-0.0015 0,0.585643 0,0.585644 -0.157674,0 -0.157673,0 0,-1.419059 z m 0.957595,-0.07002 c 0.317186,-0.08809 0.457155,-0.374586 0.35294,-0.722426 -0.06852,-0.228699 -0.243269,-0.319389 -0.668579,-0.346977 l -0.326609,-0.02118 0,0.569043 0,0.569043 0.236509,-2.52e-4 c 0.130081,-1.4e-4 0.312663,-0.0214 0.405739,-0.04725 l 0,1e-6 z"
- id="path3352"
+ d="m 27.567493,45.252146 c -0.46948,0 -0.933016,-0.02903 -1.389761,-0.08296 l 1.178368,1.948634 1.161389,-1.918769 c -0.314968,0.02489 -0.629086,0.05309 -0.949996,0.05309 z"
+ id="path3003-9"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d="m 12.297723,14.172444 0,-0.157674 0.47302,0 0.473019,0 0,0.157674 0,0.157673 -0.473019,0 -0.47302,0 0,-0.157673 z"
- id="path3354"
+ d="m 38.317981,14.929279 c -1.837168,0 -3.360217,1.289964 -3.68707,2.992219 1.578232,1.115757 2.934884,2.584076 3.968928,4.320343 1.939893,-0.142684 3.475677,-1.709721 3.475677,-3.641764 0,-2.027442 -1.682656,-3.670798 -3.757535,-3.670798 z"
+ id="path3007-2"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d="m 13.829406,13.81716 0,-1.424172 0.394183,3.4e-4 c 0.504972,4.36e-4 0.949176,0.07091 1.092451,0.173331 0.177108,0.126601 0.278311,0.359024 0.255183,0.586055 -0.02614,0.256601 -0.150315,0.416536 -0.394975,0.508718 l -0.19808,0.07463 0.135149,0.04854 c 0.402858,0.144687 0.541576,0.312906 0.538376,0.652871 -0.0028,0.300273 -0.142773,0.536311 -0.396505,0.668755 -0.158242,0.0826 -0.281956,0.100449 -0.806351,0.116336 l -0.619431,0.01877 0,-1.424172 z m 1.189371,1.080834 c 0.205986,-0.08607 0.297263,-0.232772 0.297263,-0.477778 0,-0.391932 -0.222596,-0.540594 -0.809444,-0.540594 l -0.361843,0 0,0.540594 0,0.540594 0.361843,0 c 0.207542,0 0.425951,-0.02679 0.512181,-0.06282 z m 0.02747,-1.356506 c 0.161495,-0.08351 0.257324,-0.352482 0.193645,-0.543518 -0.07596,-0.227892 -0.238346,-0.304742 -0.689489,-0.326311 l -0.405653,-0.01939 0,0.478531 0,0.47853 0.385157,0 c 0.254915,0 0.429518,-0.02294 0.51634,-0.06784 z"
- id="path3356"
+ d="m 38.787461,38.290488 c -1.039138,1.851575 -2.42805,3.426908 -4.072502,4.609029 0.442312,1.546298 1.878767,2.686942 3.603022,2.686942 2.07403,0 3.757535,-1.642527 3.757535,-3.669969 0,-1.870656 -1.437304,-3.397874 -3.288055,-3.626002 z"
+ id="path3009-6"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d="m 6.4998363,4.4192258 c 0,-0.1362748 0.00845,-0.1920236 0.018767,-0.1238862 0.010322,0.068137 0.010322,0.1796349 0,0.2477723 -0.010322,0.068137 -0.018767,0.012389 -0.018767,-0.1238861 z"
- id="path3358"
+ d="m 16.340734,38.277215 c -1.912727,0.170889 -3.41625,1.724653 -3.41625,3.639275 0,2.026612 1.680958,3.669969 3.755837,3.669969 1.752271,0 3.212497,-1.177974 3.626793,-2.764091 -1.598607,-1.174655 -2.950165,-2.728419 -3.96638,-4.545153 z"
+ id="path3011-6"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d=""
- id="path3360"
+ d="m 20.375881,18.007772 c -0.291196,-1.744563 -1.828678,-3.078493 -3.69556,-3.078493 -2.074879,0 -3.755837,1.643356 -3.755837,3.669968 0,1.97601 1.601155,3.575399 3.603872,3.655037 1.006876,-1.694789 2.319381,-3.139051 3.847525,-4.246512 z"
+ id="path3013-4"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d="M 6.4863366,6.7944955 C 6.2143608,6.6992443 6.1711413,6.5450045 6.1710601,5.6693495 l -7e-5,-0.7545792 -0.1576733,0 c -0.204508,0 -0.2067862,-0.095041 -0.00459,-0.1914616 0.1212141,-0.057803 0.1688609,-0.1205011 0.228868,-0.3011655 0.05601,-0.1686289 0.09835,-0.228165 0.1622628,-0.228165 0.074789,0 0.086478,0.033491 0.086478,0.2477723 l 0,0.2477723 0.2702971,0 c 0.2582838,0 0.270297,0.00501 0.270297,0.1126237 0,0.1076183 -0.012013,0.1126238 -0.270297,0.1126238 l -0.2702971,0 0,0.7332931 c 0,0.8719524 0.022458,0.9335386 0.3404258,0.9335386 0.1681065,0 0.2001683,0.014006 0.2001683,0.08744 0,0.048092 -0.015359,0.096933 -0.03413,0.108534 -0.092212,0.05699 -0.3659374,0.066134 -0.5064639,0.016919 z"
- id="path3362"
+ d="m 27.567493,15.62362 c 1.619832,0 3.164955,0.340948 4.599711,0.935742 0.629086,-0.892605 1.000085,-1.971862 1.000085,-3.138221 0,-3.058584 -2.537567,-5.5389654 -5.668563,-5.5389654 -3.130146,0 -5.667713,2.4803814 -5.667713,5.5389654 0,1.18461 0.383734,2.280457 1.032345,3.180529 1.463622,-0.62134 3.04525,-0.97805 4.704135,-0.97805 z"
+ id="path3015-9"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3017-5"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none">
+ <path
+ d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z"
+ id="path3019-0"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3021-4"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none">
+ <path
+ d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z"
+ id="path3023-8"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z"
+ id="path3025-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z"
+ id="path3027-1"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z"
+ id="path3029-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z"
+ id="path3031-2"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z"
+ id="path3033-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
</g>
+ <path
+ inkscape:connector-curvature="0"
+ d="m 36.727769,13.00053 2.437818,-2.366117 1.200984,0.84248 1.416085,1.200984 0.985882,1.272684 0.914181,1.487786 -2.366117,2.509519 -0.896257,-1.505711 -2.186866,-2.366117 -1.50571,-1.075508 z"
+ id="path3255"
+ style="fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:1px;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 34.039,15.760999 2.294417,-2.079315 1.200984,0.84248 1.416085,1.200984 0.985882,1.272684 0.914181,1.487786 -2.079315,1.864214 L 37.803277,19.202624 35.47301,16.979908 34.039,15.760999 z"
+ id="path3253"
+ style="fill:#000000;stroke:#ffffff;stroke-width:1px;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 14.58471,38.455767 0.891754,-3.80169 18.820708,-18.210561 -0.469344,-0.680549 2.252852,-2.135517 5.115854,5.115853 -2.229385,2.135517 -0.774419,-0.539747 -19.05538,18.022824 -3.70782,0.657082 -0.84482,-0.563212 z"
+ id="path2822"
+ style="fill:#000000;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 34.643894,17.006729 3.660886,3.473148"
+ id="path3596"
+ style="fill:#000000;stroke:#ffffff;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 12.097185,41.553439 2.769132,-2.816066"
+ id="path3598"
+ style="fill:#000000;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 15.85194,34.935683 c 0,0 1.594197,0.393866 2.158983,0.93869 0.574138,0.553844 1.032558,2.158984 1.032558,2.158984"
+ id="path3600"
+ style="fill:#000000;stroke:#ffffff;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
+ <path
+ style="fill:#ffffff"
+ d="M 19.349056,35.431705 C 19.178841,35.135123 18.785498,34.737952 18.47496,34.549103 l -0.564614,-0.343363 8.07,-7.818797 c 4.438499,-4.300339 8.135227,-7.818798 8.214949,-7.818798 0.07972,0 0.552,0.413263 1.049504,0.918363 l 0.904554,0.918362 -0.544779,0.523798 c -0.299628,0.288088 -3.721029,3.517184 -7.603112,7.175769 -3.882083,3.658584 -7.347366,6.925242 -7.700629,7.25924 l -0.642296,0.607268 -0.309481,-0.53924 z"
+ id="path2990"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff"
+ d="M 41.086845,16.393162 C 40.701779,15.787758 38.87153,13.830973 38.185892,13.29165 l -0.446583,-0.351282 0.773579,-0.759211 0.773579,-0.75921 1.103351,0.892762 c 0.606843,0.49102 1.4187,1.350636 1.804126,1.910257 l 0.700775,1.017495 -0.368509,0.517008 c -0.202679,0.284355 -0.532115,0.664852 -0.732079,0.845549 -0.352751,0.318761 -0.373799,0.312457 -0.707286,-0.211856 l 0,0 z"
+ id="path2992"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff"
+ d="m 37.243818,17.583377 c -1.333982,-1.264073 -1.591222,-1.592584 -1.400927,-1.789073 0.190815,-0.197026 0.522406,0.04863 1.828095,1.354317 1.122173,1.122174 1.537468,1.652532 1.400927,1.789073 -0.136541,0.136541 -0.678467,-0.264937 -1.828095,-1.354317 l 0,0 z"
+ id="path2994"
+ inkscape:connector-curvature="0" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.86668491px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+ x="34.952782"
+ y="43.921482"
+ id="text3190"
+ sodipodi:linespacing="125%"
+ transform="scale(0.85843144,1.1649154)"><tspan
+ sodipodi:role="line"
+ id="tspan3192"
+ x="34.952782"
+ y="43.921482">Right</tspan></text>
</svg>
diff --git a/icons/right_top.svg b/icons/right_top.svg
index bba9810..d67c31d 100644
--- a/icons/right_top.svg
+++ b/icons/right_top.svg
@@ -9,35 +9,14 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16px"
- height="16px"
- id="svg3017"
- version="1.1"
+ version="1.0"
+ width="55"
+ height="55"
+ id="svg2"
inkscape:version="0.48.0 r9654"
sodipodi:docname="right_top.svg">
- <defs
- id="defs3019" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="22.197802"
- inkscape:cx="8"
- inkscape:cy="10.328398"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
- inkscape:window-width="1366"
- inkscape:window-height="701"
- inkscape:window-x="0"
- inkscape:window-y="0"
- inkscape:window-maximized="1" />
<metadata
- id="metadata3022">
+ id="metadata13">
<rdf:RDF>
<cc:Work
rdf:about="">
@@ -48,267 +27,178 @@
</cc:Work>
</rdf:RDF>
</metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1366"
+ inkscape:window-height="701"
+ id="namedview11"
+ showgrid="false"
+ inkscape:zoom="5.4545455"
+ inkscape:cx="27.5"
+ inkscape:cy="16.853243"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" />
+ <defs
+ id="defs5" />
+ <text
+ xml:space="preserve"
+ style="font-size:6px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+ x="3.3"
+ y="12.65"
+ id="text3004"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3006"
+ x="3.3"
+ y="12.65" /></text>
+ <path
+ d="m 50.694743,28.141667 c 0,11.875822 -9.769034,21.503077 -21.819744,21.503077 -12.050712,0 -21.8197421,-9.627255 -21.8197421,-21.503077 0,-11.875822 9.7690301,-21.5030767 21.8197421,-21.5030767 12.05071,0 21.819744,9.6272547 21.819744,21.5030767 l 0,0 z"
+ id="path2387"
+ style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:3.74384761;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
<g
- id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="1.4415842"
- y="15.279208"
- id="text3025"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3027"
- x="1.4415842"
- y="15.279208"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;writing-mode:lr-tb;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="3.3336635"
- y="8.7019796"
- id="text3029"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3031" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="3.1985149"
- y="11.314851"
- id="text3033"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3035" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="1.8920792"
- y="14.062871"
- id="text3056"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3058"
- x="1.8920792"
- y="14.062871"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;writing-mode:lr-tb;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans"> </tspan></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122%;letter-spacing:0px;word-spacing:0px;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.2163366"
- y="3.791584"
- id="text3117"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3119"
- x="1.2163366"
- y="3.791584" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="8.9198017"
- y="4.5123763"
- id="text3154"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- x="8.9198017"
- y="4.5123763"
- id="tspan3158" /><tspan
- sodipodi:role="line"
- x="8.9198017"
- y="14.272377"
- id="tspan3160" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="2.0722773"
- y="14.738614"
- id="text3162"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3164"
- x="2.0722773"
- y="14.738614" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.0361387"
- y="15.144059"
- id="text3166"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3168"
- x="1.0361387"
- y="15.144059" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="0.58564359"
- y="4.1069307"
- id="text3191"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3193" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.0811881"
- y="10.278713"
- id="text3216"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- x="1.0811881"
- y="10.278713"
- id="tspan3220" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.0811881"
- y="15.459406"
- id="text3224"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3226"
- x="1.0811881"
- y="15.459406" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.4415842"
- y="6.8099008"
- id="text3228"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3230"
- x="1.4415842"
- y="6.8099008" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="0.27029702"
- y="6.8099008"
- id="text3232"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3234"
- x="0.27029702"
- y="6.8099008" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="9.7757425"
- y="15.234158"
- id="text3255"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3257"
- x="9.7757425"
- y="15.234158" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="0.58564359"
- y="4.3321781"
- id="text3278"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3280"
- x="0.58564359"
- y="4.3321781" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="0.58564359"
- y="12.035644"
- id="text3282"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3284"
- x="0.58564359"
- y="12.035644">text edit</tspan></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="11.127228"
- y="3.9717822"
- id="text3305"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3307"
- x="11.127228"
- y="3.9717822" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="9.7306929"
- y="4.0618811"
- id="text3309"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3311"
- x="9.7306929"
- y="4.0618811">R-T</tspan></text>
- <path
- style="fill:#ffffff"
- d="M 1.31519,12.028196 C 1.2255238,12.00149 1.132248,11.926978 1.0788485,11.839399 1.0002829,11.710546 0.99061534,11.609719 0.99046537,10.917617 l -1.684e-4,-0.777104 -0.15767327,0 c -0.20450798,0 -0.20678618,-0.09504 -0.004589,-0.1914617 0.12121407,-0.057803 0.1688609,-0.1205011 0.22886799,-0.3011655 0.05601,-0.1686289 0.09835,-0.228165 0.1622628,-0.228165 0.074789,0 0.086478,0.033491 0.086478,0.2477723 l 0,0.2477723 0.270297,0 c 0.2582839,0 0.2702971,0.00501 0.2702971,0.1126236 0,0.107618 -0.012013,0.112624 -0.2702971,0.112624 l -0.270297,0 0,0.758859 c 0,0.868582 0.0153,0.907973 0.3526809,0.907973 0.1559756,0 0.1879132,0.01486 0.1879132,0.08744 0,0.04809 -0.015359,0.09693 -0.03413,0.108534 -0.082981,0.05129 -0.3614494,0.06523 -0.4969173,0.02488 z"
- id="path3477"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 2.8684953,12.014328 C 2.6044657,11.942122 2.369772,11.725974 2.2690589,11.462261 2.1542315,11.161589 2.1979639,10.577965 2.3554591,10.30922 2.6393857,9.8247356 3.2324686,9.7459636 3.6101364,10.142576 c 0.1610986,0.16918 0.2633289,0.457812 0.2633289,0.743471 l 0,0.110407 -0.6820176,0 -0.6820175,0 0.026866,0.226839 c 0.053703,0.453443 0.3428046,0.641766 0.8416248,0.548243 0.1362747,-0.02555 0.2832487,-0.06052 0.3266089,-0.07772 0.064326,-0.02551 0.078837,-0.0068 0.078837,0.101575 0,0.114863 -0.022859,0.139387 -0.1689356,0.181242 -0.3027981,0.08676 -0.525392,0.09801 -0.7459354,0.03769 l 0,0 z m 0.644574,-1.380508 c 0,-0.169853 -0.1072985,-0.385133 -0.2227522,-0.446922 -0.1459495,-0.07811 -0.4301392,-0.0548 -0.5579872,0.04576 -0.1038301,0.08167 -0.2093924,0.323967 -0.2100985,0.482233 -1.858e-4,0.04165 0.1287567,0.05631 0.4952933,0.05631 l 0.4955446,0 0,-0.137386 z"
- id="path3479"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 4.5522478,11.487461 4.9174629,10.942329 4.5754461,10.428797 4.2334294,9.9152654 l 0.1712048,0 c 0.1673451,0 0.1767446,0.00914 0.4169239,0.4052906 0.1351455,0.22291 0.2558552,0.404877 0.2682439,0.404371 0.012389,-5.06e-4 0.1298331,-0.182887 0.2609877,-0.405291 0.2271269,-0.3851475 0.2458657,-0.4043706 0.3941832,-0.4043706 0.085646,0 0.1557202,0.010812 0.1557202,0.024027 0,0.013215 -0.1434507,0.2378361 -0.3187793,0.4991591 -0.1753286,0.261323 -0.3079789,0.503278 -0.2947786,0.537678 0.0132,0.0344 0.1667872,0.275364 0.341304,0.535477 0.1745169,0.260113 0.3173034,0.483745 0.3173034,0.49696 0,0.01321 -0.070111,0.02403 -0.1558025,0.02403 -0.1484333,0 -0.1681426,-0.02022 -0.4167079,-0.427567 -0.143498,-0.235162 -0.2733365,-0.427749 -0.2885299,-0.42797 -0.015193,-2.22e-4 -0.1441435,0.192183 -0.2865559,0.427567 -0.2561908,0.42344 -0.2607955,0.42797 -0.4350226,0.42797 l -0.176091,0 0.365215,-0.545131 z"
- id="path3481"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 6.8016832,12.020238 C 6.5297073,11.924987 6.4864879,11.770747 6.4864066,10.895092 l -7e-5,-0.754579 -0.1576732,0 c -0.204508,0 -0.2067862,-0.09504 -0.00459,-0.1914617 0.121214,-0.057803 0.1688609,-0.1205011 0.228868,-0.3011655 0.056009,-0.1686289 0.098349,-0.228165 0.1622627,-0.228165 0.07479,0 0.086479,0.033491 0.086479,0.2477723 l 0,0.2477723 0.270297,0 c 0.2582838,0 0.270297,0.00501 0.270297,0.1126236 0,0.107618 -0.012013,0.112624 -0.270297,0.112624 l -0.270297,0 0,0.733293 c 0,0.871952 0.022458,0.933539 0.3404257,0.933539 0.1681065,0 0.2001683,0.01401 0.2001683,0.08744 0,0.04809 -0.015359,0.09693 -0.03413,0.108534 -0.092212,0.05699 -0.3659374,0.06613 -0.5064638,0.01692 z"
- id="path3483"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 9.4323342,12.028335 C 9.0030378,11.927322 8.7388119,11.524703 8.7388119,10.971568 c 0,-0.358129 0.097634,-0.630988 0.2999517,-0.838278 0.5297235,-0.5427444 1.3654204,-0.118222 1.3666284,0.694228 l 2.52e-4,0.168936 -0.675743,0 -0.6757426,0 0,0.148127 c 0,0.08147 0.045613,0.238581 0.1013614,0.349134 0.1341402,0.266008 0.3397027,0.344089 0.7320545,0.278062 0.1486637,-0.02502 0.3057737,-0.05983 0.3491337,-0.07735 0.06446,-0.02606 0.07884,-0.0076 0.07884,0.100971 0,0.11454 -0.02327,0.139755 -0.168936,0.183057 -0.2679836,0.07966 -0.5145375,0.09688 -0.7142748,0.04988 l 0,0 z M 10.045248,10.63382 c 0,-0.169853 -0.107299,-0.385133 -0.2227526,-0.446922 -0.2491687,-0.133351 -0.5866117,-0.0032 -0.6951788,0.268142 -0.1277254,0.319218 -0.1318025,0.316166 0.4223864,0.316166 l 0.495545,0 0,-0.137386 z"
- id="path3485"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="m 11.492364,12.032499 c -0.222435,-0.05252 -0.371384,-0.18175 -0.497641,-0.431771 -0.09467,-0.187477 -0.111626,-0.283405 -0.110774,-0.626799 0.0015,-0.621886 0.191127,-0.947789 0.618246,-1.0628006 0.225892,-0.060827 0.456979,-0.00187 0.633338,0.1615696 0.06698,0.06208 0.130874,0.112864 0.141986,0.112864 0.01111,0 0.0202,-0.2635392 0.0202,-0.5856431 l 0,-0.5856436 0.157673,0 0.157673,0 0,1.5091587 0,1.509158 -0.135148,0 c -0.109917,0 -0.135277,-0.01892 -0.135839,-0.101361 -0.0014,-0.198815 -0.06381,-0.223112 -0.202199,-0.07866 -0.106728,0.1114 -0.379271,0.238326 -0.472853,0.220211 -0.01239,-0.0024 -0.09099,-0.02052 -0.174666,-0.04028 z m 0.530954,-0.290604 c 0.18785,-0.09714 0.252009,-0.299197 0.251006,-0.790491 -0.0012,-0.611603 -0.138456,-0.810891 -0.558289,-0.810891 -0.347893,0 -0.508318,0.259253 -0.511933,0.827304 -0.0025,0.387238 0.06932,0.62667 0.224492,0.748724 0.137527,0.108179 0.411936,0.119877 0.594724,0.02535 z"
- id="path3487"
- inkscape:connector-curvature="0" />
+ transform="matrix(1.0419883,0.08962519,-0.06100752,1.0005359,2.3742569,-3.2361949)"
+ id="g2937-8">
<path
- style="fill:#ffffff"
- d="m 13.333861,10.973929 0,-1.0586636 0.157674,0 0.157673,0 0,1.0586636 0,1.058663 -0.157673,0 -0.157674,0 0,-1.058663 z"
- id="path3489"
+ d="m 27.567493,45.252146 c -0.46948,0 -0.933016,-0.02903 -1.389761,-0.08296 l 1.178368,1.948634 1.161389,-1.918769 c -0.314968,0.02489 -0.629086,0.05309 -0.949996,0.05309 z"
+ id="path3003-9"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d="m 13.335306,9.4224208 c -0.03401,-0.063551 -0.03536,-0.1195255 -0.0043,-0.1775979 0.107644,-0.2011346 0.336943,-0.1203115 0.310785,0.1095452 -0.01206,0.1060051 -0.0396,0.1357548 -0.135983,0.1468893 -0.08514,0.00984 -0.135533,-0.013462 -0.170521,-0.078837 z"
- id="path3491"
+ d="m 38.317981,14.929279 c -1.837168,0 -3.360217,1.289964 -3.68707,2.992219 1.578232,1.115757 2.934884,2.584076 3.968928,4.320343 1.939893,-0.142684 3.475677,-1.709721 3.475677,-3.641764 0,-2.027442 -1.682656,-3.670798 -3.757535,-3.670798 z"
+ id="path3007-2"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d="m 14.739943,12.028196 c -0.08967,-0.02671 -0.182942,-0.101218 -0.236342,-0.188797 -0.07856,-0.128853 -0.08823,-0.22968 -0.08838,-0.921782 l -1.68e-4,-0.777104 -0.157674,0 c -0.200927,0 -0.208018,-0.09496 -0.01395,-0.1868667 0.109989,-0.05209 0.161069,-0.1200886 0.217645,-0.2897326 0.05461,-0.1637579 0.09945,-0.2254289 0.171627,-0.2360637 0.09026,-0.0133 0.0977,0.0047 0.0977,0.2365099 l 0,0.2509055 0.270297,0 c 0.258284,0 0.270297,0.00501 0.270297,0.1126236 0,0.107618 -0.01201,0.112624 -0.270297,0.112624 l -0.270297,0 0,0.758859 c 0,0.868582 0.0153,0.907973 0.352681,0.907973 0.155976,0 0.187913,0.01486 0.187913,0.08744 0,0.04809 -0.01536,0.09693 -0.03413,0.108534 -0.08298,0.05129 -0.361449,0.06523 -0.496917,0.02488 z"
- id="path3493"
+ d="m 38.787461,38.290488 c -1.039138,1.851575 -2.42805,3.426908 -4.072502,4.609029 0.442312,1.546298 1.878767,2.686942 3.603022,2.686942 2.07403,0 3.757535,-1.642527 3.757535,-3.669969 0,-1.870656 -1.437304,-3.397874 -3.288055,-3.626002 z"
+ id="path3009-6"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d="m 14.054654,2.7749188 0,-1.2839109 -0.405446,0 -0.405446,0 0,-0.1351485 0,-0.1351485 0.968565,0 0.968564,0 0,0.1333946 0,0.1333946 -0.394183,0.013016 -0.394183,0.013016 -0.01196,1.2726485 -0.01196,1.2726485 -0.156972,0 -0.156971,0 0,-1.2839109 z"
- id="path3495"
+ d="m 16.340734,38.277215 c -1.912727,0.170889 -3.41625,1.724653 -3.41625,3.639275 0,2.026612 1.680958,3.669969 3.755837,3.669969 1.752271,0 3.212497,-1.177974 3.626793,-2.764091 -1.598607,-1.174655 -2.950165,-2.728419 -3.96638,-4.545153 z"
+ id="path3011-6"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d="m 12.252673,3.0001663 0,-0.1576732 0.47302,0 0.47302,0 0,0.1576732 0,0.1576733 -0.47302,0 -0.47302,0 0,-0.1576733 z"
- id="path3497"
+ d="m 20.375881,18.007772 c -0.291196,-1.744563 -1.828678,-3.078493 -3.69556,-3.078493 -2.074879,0 -3.755837,1.643356 -3.755837,3.669968 0,1.97601 1.601155,3.575399 3.603872,3.655037 1.006876,-1.694789 2.319381,-3.139051 3.847525,-4.246512 z"
+ id="path3013-4"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d="m 10.135347,2.6397703 0,-1.4190594 0.349133,2.609e-4 c 0.896309,6.699e-4 1.257205,0.1969098 1.306549,0.7104456 0.03035,0.3158735 -0.102239,0.5998924 -0.344703,0.7383796 -0.101226,0.057817 -0.184204,0.1201364 -0.184395,0.1384877 -1.91e-4,0.018351 0.161831,0.2972846 0.360049,0.6198519 0.198218,0.3225673 0.360396,0.5964326 0.360396,0.6085896 0,0.012157 -0.07722,0.022104 -0.171608,0.022104 l -0.171609,0 -0.335198,-0.5841633 -0.335199,-0.5841632 -0.259034,-0.00148 -0.259035,-0.00148 0,0.5856435 0,0.5856436 -0.157673,0 -0.157673,0 0,-1.4190594 z m 0.957595,-0.070024 C 11.410128,2.4816602 11.550097,2.1951607 11.445881,1.8473208 11.377361,1.6186216 11.202613,1.5279312 10.777302,1.5003442 l -0.326609,-0.021185 0,0.5690432 0,0.5690431 0.23651,-2.522e-4 c 0.13008,-1.397e-4 0.312663,-0.0214 0.405739,-0.047248 l 0,1.1e-6 z"
- id="path3499"
+ d="m 27.567493,15.62362 c 1.619832,0 3.164955,0.340948 4.599711,0.935742 0.629086,-0.892605 1.000085,-1.971862 1.000085,-3.138221 0,-3.058584 -2.537567,-5.5389654 -5.668563,-5.5389654 -3.130146,0 -5.667713,2.4803814 -5.667713,5.5389654 0,1.18461 0.383734,2.280457 1.032345,3.180529 1.463622,-0.62134 3.04525,-0.97805 4.704135,-0.97805 z"
+ id="path3015-9"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3017-5"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none">
+ <path
+ d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z"
+ id="path3019-0"
+ style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)"
+ id="g3021-4"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none">
+ <path
+ d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z"
+ id="path3023-8"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z"
+ id="path3025-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z"
+ id="path3027-1"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z"
+ id="path3029-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z"
+ id="path3031-2"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z"
+ id="path3033-7"
+ style="fill:none;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
</g>
+ <path
+ inkscape:connector-curvature="0"
+ d="m 34.390171,12.181507 2.437818,-2.3661174 1.200984,0.8424804 1.416085,1.200984 0.985882,1.272684 0.914181,1.487786 -2.366117,2.509519 -0.896257,-1.505711 -2.186866,-2.366117 -1.50571,-1.075508 z"
+ id="path3255"
+ style="fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:1px;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 31.701402,14.941976 2.294417,-2.079315 1.200984,0.84248 1.416085,1.200984 0.985882,1.272684 0.914181,1.487786 -2.079315,1.864214 -0.967957,-1.147208 -2.330267,-2.222716 -1.43401,-1.218909 z"
+ id="path3253"
+ style="fill:#000000;stroke:#ffffff;stroke-width:1px;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 12.247112,37.636743 0.891754,-3.80169 18.820708,-18.21056 -0.469344,-0.680549 2.252852,-2.135517 5.115854,5.115853 -2.229385,2.135517 -0.774419,-0.539747 -19.05538,18.022823 -3.70782,0.657082 -0.84482,-0.563212 z"
+ id="path2822"
+ style="fill:#000000;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 32.306296,16.187706 3.660886,3.473148"
+ id="path3596"
+ style="fill:#000000;stroke:#ffffff;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="M 9.7595867,40.734415 12.528719,37.918349"
+ id="path3598"
+ style="fill:#000000;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 13.514342,34.116659 c 0,0 1.594197,0.393866 2.158983,0.93869 0.574138,0.553844 1.032558,2.158984 1.032558,2.158984"
+ id="path3600"
+ style="fill:#000000;stroke:#ffffff;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
+ <path
+ style="fill:#ffffff"
+ d="M 17.011458,34.612681 C 16.841243,34.316099 16.4479,33.918928 16.137362,33.730079 l -0.564614,-0.343363 8.07,-7.818797 c 4.438499,-4.300338 8.135227,-7.818797 8.214949,-7.818797 0.07972,0 0.552,0.413263 1.049504,0.918363 l 0.904554,0.918362 -0.544779,0.523798 c -0.299628,0.288088 -3.721029,3.517184 -7.603112,7.175768 -3.882083,3.658584 -7.347366,6.925242 -7.700629,7.25924 l -0.642296,0.607268 -0.309481,-0.53924 z"
+ id="path2990"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff"
+ d="M 38.749247,15.574139 C 38.364181,14.968735 36.533932,13.01195 35.848294,12.472627 l -0.446583,-0.351282 0.773579,-0.759211 0.773579,-0.75921 1.103351,0.892762 c 0.606843,0.49102 1.4187,1.350636 1.804126,1.910257 l 0.700775,1.017495 -0.368509,0.517008 c -0.202679,0.284355 -0.532115,0.664852 -0.732079,0.845549 -0.352751,0.318761 -0.373799,0.312457 -0.707286,-0.211856 l 0,0 z"
+ id="path2992"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff"
+ d="m 34.90622,16.764354 c -1.333982,-1.264073 -1.591222,-1.592584 -1.400927,-1.789073 0.190815,-0.197026 0.522406,0.04863 1.828095,1.354317 1.122173,1.122174 1.537468,1.652532 1.400927,1.789073 -0.136541,0.136541 -0.678467,-0.264937 -1.828095,-1.354317 l 0,0 z"
+ id="path2994"
+ inkscape:connector-curvature="0" />
+ <text
+ xml:space="preserve"
+ style="font-size:10.73246765px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+ x="40.364532"
+ y="8.295579"
+ id="text3144"
+ sodipodi:linespacing="125%"
+ transform="scale(0.81362788,1.2290631)"><tspan
+ sodipodi:role="line"
+ id="tspan3146"
+ x="40.364532"
+ y="8.295579">Right</tspan></text>
</svg>
diff --git a/icons/sharpen.svg b/icons/sharpen.svg
index c6b9524..cdf9858 100644
--- a/icons/sharpen.svg
+++ b/icons/sharpen.svg
@@ -9,261 +9,177 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16px"
- height="16px"
- id="svg3017"
- version="1.1"
+ version="1.0"
+ width="45"
+ height="45"
+ id="svg2"
inkscape:version="0.48.0 r9654"
- sodipodi:docname="sharpen.svg">
- <defs
- id="defs3019" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="22.197802"
- inkscape:cx="8"
- inkscape:cy="10.328398"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
- inkscape:window-width="1366"
- inkscape:window-height="701"
- inkscape:window-x="0"
- inkscape:window-y="0"
- inkscape:window-maximized="1" />
+ sodipodi:docname="debugon.svg">
<metadata
- id="metadata3022">
+ id="metadata39">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
+ <dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview37"
+ showgrid="false"
+ inkscape:zoom="6.6666667"
+ inkscape:cx="22.5"
+ inkscape:cy="22.5"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg2" />
+ <defs
+ id="defs4" />
<g
- id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="1.4415842"
- y="15.279208"
- id="text3025"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3027"
- x="1.4415842"
- y="15.279208"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;writing-mode:lr-tb;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="3.3336635"
- y="8.7019796"
- id="text3029"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3031" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="3.1985149"
- y="11.314851"
- id="text3033"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3035" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="1.8920792"
- y="14.062871"
- id="text3056"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3058"
- x="1.8920792"
- y="14.062871"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;writing-mode:lr-tb;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans"> </tspan></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122%;letter-spacing:0px;word-spacing:0px;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.2163366"
- y="3.791584"
- id="text3117"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3119"
- x="1.2163366"
- y="3.791584" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="8.9198017"
- y="4.5123763"
- id="text3154"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- x="8.9198017"
- y="4.5123763"
- id="tspan3158" /><tspan
- sodipodi:role="line"
- x="8.9198017"
- y="14.272377"
- id="tspan3160" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="2.0722773"
- y="14.738614"
- id="text3162"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3164"
- x="2.0722773"
- y="14.738614" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.0361387"
- y="15.144059"
- id="text3166"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3168"
- x="1.0361387"
- y="15.144059" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="0.58564359"
- y="4.1069307"
- id="text3191"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3193" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.0811881"
- y="10.278713"
- id="text3216"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- x="1.0811881"
- y="10.278713"
- id="tspan3220" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.0811881"
- y="15.459406"
- id="text3224"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3226"
- x="1.0811881"
- y="15.459406" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="1.4415842"
- y="6.8099008"
- id="text3228"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3230"
- x="1.4415842"
- y="6.8099008" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="0.27029702"
- y="6.8099008"
- id="text3232"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3234"
- x="0.27029702"
- y="6.8099008" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="9.7757425"
- y="15.234158"
- id="text3255"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3257"
- x="9.7757425"
- y="15.234158" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="0.58564359"
- y="4.3321781"
- id="text3278"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3280"
- x="0.58564359"
- y="4.3321781" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="0.58564359"
- y="12.035644"
- id="text3282"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3284"
- x="0.58564359"
- y="12.035644" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="11.127228"
- y="3.9717822"
- id="text3305"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3307"
- x="11.127228"
- y="3.9717822" /></text>
- <text
- xml:space="preserve"
- style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
- x="9.7306929"
- y="4.0618811"
- id="text3309"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3311"
- x="9.7306929"
- y="4.0618811" /></text>
- <path
- style="fill:none;stroke:#000000;stroke-width:0.8239994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 11.002501,3.2080392 4.9124948,6.2985844 11.080081,9.1759885 5.0288643,12.799386"
- id="path3332"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff"
- d="M 5.0515223,12.788829 C 4.9460106,12.613439 4.8759831,12.455484 4.8959058,12.437817 4.9158284,12.420151 6.1249882,11.691116 7.5829277,10.81774 9.040867,9.9443642 10.216659,9.2151245 10.195799,9.1972069 10.174939,9.1792898 8.7945607,8.5296426 7.1282921,7.7535469 5.4620235,6.9774511 4.0987128,6.3276481 4.0987128,6.3095402 c 0,-0.023931 6.4309442,-3.3134065 6.6745142,-3.4140634 0.03891,-0.016078 0.383746,0.6540164 0.35104,0.6821429 -0.0112,0.00963 -1.200777,0.6134422 -2.6435132,1.3418086 -1.4427364,0.7283663 -2.6174723,1.3426753 -2.6105242,1.365131 0.00941,0.030426 3.5294761,1.6921331 5.9037704,2.7869793 0.127945,0.058999 0.08993,0.083372 -3.1759903,2.0364084 -1.8180167,1.087183 -3.3165467,1.981888 -3.3300665,1.988234 -0.01352,0.0063 -0.1109092,-0.131962 -0.2164209,-0.307352 l 0,0 z"
- id="path3538"
- inkscape:connector-curvature="0" />
+ transform="matrix(0.81818179,0,0,0.81818179,2.9325954e-7,1.8913349e-6)"
+ id="g2886">
<path
- style="fill:#f5f5f5"
- d="m 5.1900049,12.937614 c -0.04856,-0.06568 -0.12958,-0.200353 -0.1800445,-0.299272 L 4.9182066,12.45849 7.0409741,11.175615 C 9.2857494,9.8190063 10.226455,9.2337313 10.223877,9.1953207 10.223015,9.1824658 9.3158303,8.7474872 8.2079119,8.2287007 5.3291274,6.8807003 4.1901288,6.3370951 4.1904549,6.311305 4.1907985,6.2841324 5.0537343,5.8368084 8.2863131,4.1881158 9.9109802,3.3594968 10.756581,2.9510973 10.790059,2.978882 c 0.08901,0.073869 0.30051,0.5482253 0.261434,0.5863396 C 11.030768,3.585436 9.9999205,4.1186275 8.7607204,4.7500914 6.3041893,6.001875 5.8708344,6.2352285 5.892471,6.2945896 5.9088771,6.3396005 7.287877,7.0047805 9.7270805,8.1442675 10.657778,8.579048 11.498892,8.9751917 11.596223,9.0245876 l 0.176965,0.089811 -0.109391,0.085416 C 11.53377,9.3013447 9.0793965,10.790151 6.8621429,12.112466 l -1.5838472,0.944568 -0.088291,-0.11942 0,0 z"
- id="path3720"
- inkscape:connector-curvature="0" />
+ d="m 12.3583,20.48583 c 0,6.948279 -1.644946,12.580972 -3.6740891,12.580972 -2.0291434,0 -3.6740891,-5.632693 -3.6740891,-12.580972 0,-6.948279 1.6449457,-12.5809723 3.6740891,-12.5809723 2.0291431,0 3.6740891,5.6326933 3.6740891,12.5809723 l 0,0 z"
+ transform="matrix(7.4848487,0,0,2.1858407,-37.500004,-17.278762)"
+ id="path3188"
+ style="fill:#00ff00;fill-opacity:1;stroke:none" />
+ <g
+ transform="matrix(1.5,0,0,1.5,-13.078338,-13.158384)"
+ id="g3188">
+ <path
+ d="m 27.377856,20.343519 c 0.943144,-1.32305 2.909066,-2.23143 3.443893,-2.052418 0.816335,0.273235 2.634387,1.285134 2.828305,1.870614 0.363444,1.097313 -0.440961,2.212871 -0.661443,3.319307"
+ id="path3252"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="m 31.312226,33.70644 c -3.075459,5.326852 -8.151812,8.153707 -11.338352,6.313958 -3.18654,-1.83975 -3.276587,-7.649428 -0.201128,-12.97628 3.07546,-5.326852 8.151812,-8.153707 11.338352,-6.313958 3.18654,1.83975 3.276588,7.649428 0.201128,12.97628 l 0,0 z"
+ id="path3197"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.51091182;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 30.640788,20.96543 c -3.356038,6.044559 -3.301174,5.949533 -3.301174,5.949533"
+ id="path3199"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="m 23.640267,22.485322 c 0.955579,1.892858 2.334494,3.24269 3.831245,4.497123 0.02734,0.02291 3.988592,1.409612 5.914011,1.031489"
+ id="path3201"
+ style="fill:none;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ d="m 22.8141,25.484531 c 2.380046,2.460708 2.406938,2.476234 2.406938,2.476234"
+ id="path3203"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 21.785315,26.831706 c 2.380046,2.460709 2.551072,2.661318 2.551072,2.661318"
+ id="path3207"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 20.834693,28.29192 c 2.380046,2.460708 2.617044,2.733363 2.617044,2.733363"
+ id="path3209"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 20.016015,29.896225 c 2.380045,2.460709 2.551071,2.661318 2.551071,2.661318"
+ id="path3211"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 19.370877,31.63468 c 2.380046,2.460709 2.311559,2.455123 2.311559,2.455123"
+ id="path3213"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 19.111902,33.697954 c 2.252745,2.556991 1.685883,1.92411 1.685883,1.92411"
+ id="path3215"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 19.133652,36.330772 c 0.569377,0.566421 0.779483,0.823549 0.779483,0.823549"
+ id="path3217"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="M 30.786085,30.087159 C 27.465026,29.256333 27.438134,29.240807 27.438134,29.240807"
+ id="path3230"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="M 30.133789,31.6517 C 26.81273,30.820874 26.553484,30.773066 26.553484,30.773066"
+ id="path3232"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="M 29.344518,33.20507 C 26.023459,32.374244 25.668834,32.305325 25.668834,32.305325"
+ id="path3234"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="M 28.364488,34.716219 C 25.043429,33.885393 24.784183,33.837585 24.784183,33.837585"
+ id="path3236"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="M 27.18151,36.144152 C 23.860451,35.313326 23.899532,35.369845 23.899532,35.369845"
+ id="path3238"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 25.524151,37.400068 c -3.340792,-0.672439 -2.50927,-0.497963 -2.50927,-0.497963"
+ id="path3240"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="M 23.233189,38.697641 C 22.457965,38.487756 22.130232,38.434363 22.130232,38.434363"
+ id="path3242"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 38.499043,20.363658 c -0.698249,1.209401 -2.299567,1.592097 -3.576644,0.854776 -1.277077,-0.73732 -1.746312,-2.315451 -1.048064,-3.524852 0.698249,-1.209402 2.299567,-1.592098 3.576644,-0.854777 1.277077,0.73732 1.746312,2.315451 1.048064,3.524853 z"
+ id="path3244"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.84691685;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 36.397626,17.843099 c -0.197275,0.341691 -0.649694,0.449815 -1.010506,0.2415 -0.360812,-0.208315 -0.493384,-0.654183 -0.296109,-0.995875 0.197276,-0.341691 0.649695,-0.449814 1.010507,-0.241499 0.360812,0.208315 0.493384,0.654183 0.296108,0.995874 z"
+ id="path3246"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.79813904;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 32.748117,16.754734 c -0.698248,1.209401 -2.299567,1.592097 -3.576644,0.854776 -1.277077,-0.73732 -1.746311,-2.315451 -1.048063,-3.524852 0.698249,-1.209402 2.299567,-1.592098 3.576644,-0.854777 1.277077,0.73732 1.746312,2.315451 1.048063,3.524853 z"
+ id="path3248"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.84691685;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 30.781161,14.311805 c -0.197275,0.341691 -0.649694,0.449815 -1.010506,0.2415 -0.360813,-0.208315 -0.493385,-0.654183 -0.296109,-0.995875 0.197275,-0.341691 0.649695,-0.449814 1.010507,-0.241499 0.360812,0.208315 0.493384,0.654183 0.296108,0.995874 z"
+ id="path3250"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.79813904;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 32.6771,18.762402 c 1.915624,-3.421466 5.072352,-4.541771 5.072352,-4.541771 l 0,0"
+ id="path3254"
+ style="fill:none;stroke:#000000;stroke-width:0.75545591;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 32.234792,18.337256 c 2.005265,-3.369712 1.397113,-6.663671 1.397113,-6.663671 l 0,0"
+ id="path3258"
+ style="fill:none;stroke:#000000;stroke-width:0.75545591;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="M 26.988213,20.231746 L 25.8722,15.229742 22.062204,17.274526"
+ id="path3260"
+ style="fill:none;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="m 33.361036,23.684723 l 3.584614,-0.929858 2.882681,3.70167"
+ id="path3262"
+ style="fill:none;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="m 23.851158,22.042526 l -1.097622,-3.067217 -8.164934,2.756268"
+ id="path3264"
+ style="fill:none;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="m 33.777334,27.207476 l 3.47402,-0.42778 0.497902,7.4182"
+ id="path3266"
+ style="fill:none;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 20.388485,25.668558 L 19.349188,23.00868 12.485021,29.515384"
+ id="path3268"
+ style="fill:none;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="m 32.410841,31.851473 l 2.920057,-0.91739 -2.027798,9.412169"
+ id="path3270"
+ style="fill:none;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
</g>
</svg>
diff --git a/icons/solarize.svg b/icons/solarize.svg
index fcd3abe..29d2dae 100644
--- a/icons/solarize.svg
+++ b/icons/solarize.svg
@@ -9,35 +9,36 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16px"
- height="16px"
- id="svg3017"
version="1.1"
+ width="16"
+ height="16"
+ id="svg3673"
inkscape:version="0.48.0 r9654"
sodipodi:docname="solarize.svg">
- <defs
- id="defs3019" />
<sodipodi:namedview
- id="base"
pagecolor="#ffffff"
bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
inkscape:pageshadow="2"
- inkscape:zoom="22.197802"
- inkscape:cx="8"
- inkscape:cy="10.328398"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
inkscape:window-width="1366"
inkscape:window-height="701"
+ id="namedview10"
+ showgrid="false"
+ inkscape:zoom="18.75"
+ inkscape:cx="8"
+ inkscape:cy="8"
inkscape:window-x="0"
inkscape:window-y="0"
- inkscape:window-maximized="1" />
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg3673" />
+ <defs
+ id="defs3675" />
<metadata
- id="metadata3022">
+ id="metadata3678">
<rdf:RDF>
<cc:Work
rdf:about="">
@@ -50,60 +51,27 @@
</metadata>
<g
id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="1.4415842"
- y="15.279208"
- id="text3025"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3027"
- x="1.4415842"
- y="15.279208"
- style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;writing-mode:lr-tb;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="3.3336635"
- y="8.7019796"
- id="text3029"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3031" /></text>
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="3.1985149"
- y="11.314851"
- id="text3033"
- sodipodi:linespacing="122%"><tspan
- sodipodi:role="line"
- id="tspan3035" /></text>
- <text
- xml:space="preserve"
- style="font-size:30.08130264px;font-style:normal;font-weight:normal;line-height:122.00000286%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
- x="4.5824504"
- y="13.687631"
- id="text3056"
- sodipodi:linespacing="122%"
- transform="scale(1.0539496,0.94881196)"><tspan
- sodipodi:role="line"
- id="tspan3058"
- x="4.5824504"
- y="13.687631"
- style="font-size:13.53658676px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:122.00000286%;writing-mode:lr-tb;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans">S</tspan></text>
+ transform="matrix(1.4869847,0,0,1.4386095,-3.9854314,-3.1811151)">
+ <path
+ d="m 10.90198,9.2650986 a 3.1309407,3.0408416 0 1 1 -6.2618812,0 3.1309407,3.0408416 0 1 1 6.2618812,0 z"
+ transform="translate(0.54059406,-1.4866337)"
+ id="path3681"
+ style="fill:#ff0000"
+ inkscape:connector-curvature="0" />
+ <path
+ d="M 11.127228,10.458911 8.5891158,9.7098964 6.5332015,11.376105 6.4612368,8.7307588 4.2412659,7.2903548 6.7349011,6.4044554 7.418798,3.8480284 l 1.613116,2.09783 2.642642,-0.1395548 -1.496674,2.1824296 z"
+ id="path3685"
+ style="fill:#ff0000"
+ inkscape:connector-curvature="0" />
<path
- style="fill:#ffffff"
- d="M 7.4999505,13.064482 C 6.9258785,13.028615 6.1748071,12.893436 5.8215159,12.762394 l -0.2136446,-0.07925 -0.012692,-0.528001 c -0.00698,-0.290401 -0.00546,-0.528001 0.00337,-0.528001 0.00884,0 0.1631654,0.05003 0.3429562,0.111183 0.1797907,0.06115 0.5634467,0.166567 0.8525688,0.234259 0.4638097,0.108591 0.6184589,0.123341 1.3140427,0.125327 0.6430186,0.0018 0.8379499,-0.01305 1.0573076,-0.08072 C 9.9677676,11.769649 10.271086,11.426141 10.305411,10.726157 10.351238,9.7915928 9.9739995,9.4457212 8.1531683,8.7528683 7.1087414,8.3554488 6.7434343,8.1450961 6.3219796,7.6984261 5.877459,7.22731 5.6971974,6.6861798 5.7323423,5.9283842 5.7455458,5.6436887 5.7831181,5.4032794 5.8344303,5.2751664 6.2833773,4.1542629 7.5778363,3.5820961 9.3133958,3.7374209 c 0.3157982,0.028262 0.7258332,0.083542 0.9111882,0.1228437 0.359693,0.076267 0.976627,0.2637692 1.072353,0.3259161 0.04442,0.02884 0.0087,0.1443807 -0.153824,0.4969893 -0.117248,0.2544405 -0.233518,0.4500062 -0.2606,0.4383279 C 10.716379,5.0498574 10.054547,4.8620103 9.729901,4.7943531 9.2104709,4.6861025 8.272587,4.6847335 7.922008,4.7917143 7.5754612,4.8974645 7.2563861,5.127574 7.0945049,5.38849 6.9665394,5.5947416 6.9593684,5.6316379 6.9595806,6.0826981 c 1.892e-4,0.4016614 0.015492,0.5049599 0.097564,0.6586021 0.2268515,0.424671 0.6841002,0.7099947 1.8168154,1.1336945 1.2079186,0.4518301 1.9234206,0.8540271 2.2267296,1.2516859 0.59917,0.7855521 0.600482,1.9996624 0.003,2.8112324 -0.632423,0.859086 -1.8404812,1.236735 -3.6037769,1.126569 l 1.4e-6,0 z"
- id="path3597"
+ d="M 9.1000003,11.630198 7.4384394,9.5478383 4.7810775,9.7360712 6.2480683,7.5123484 5.2478782,5.0432143 7.8160893,5.7512373 9.8552997,4.0369956 9.9755507,6.6983007 12.236042,8.1079751 9.7421501,9.0447291 z"
+ id="path3687"
+ style="fill:#ff0000"
inkscape:connector-curvature="0" />
<path
- style="fill:#f5f5f5"
- d="M 7.2651854,13.022494 C 6.8554715,12.982874 5.9949121,12.806924 5.7542822,12.713575 l -0.1238862,-0.04806 0,-0.501479 c 0,-0.41176 0.011304,-0.497142 0.063183,-0.477234 0.241125,0.09253 1.2937767,0.354857 1.5655107,0.390138 0.4482986,0.0582 1.4027252,0.05671 1.7304833,-0.0027 0.3781161,-0.06855 0.8844873,-0.321344 1.0538462,-0.526113 0.180225,-0.217905 0.272189,-0.532993 0.271874,-0.931499 -3.15e-4,-0.401639 -0.05556,-0.60077 -0.226255,-0.8155618 C 9.8196439,9.4620692 9.3683244,9.2093433 8.2047314,8.7459014 7.1084139,8.3092546 6.710208,8.077644 6.3313781,7.6562941 5.8931816,7.1689141 5.741832,6.6960343 5.7740174,5.9148654 5.7924072,5.4685297 5.8090731,5.3888229 5.9375925,5.132546 6.2402425,4.52904 6.8447818,4.0842876 7.651158,3.8718961 8.152342,3.7398892 9.0274894,3.7127982 9.6848515,3.8089413 c 0.8924795,0.1305304 1.5767325,0.3347723 1.5767325,0.4706372 0,0.0687 -0.25715,0.6282467 -0.349051,0.759518 -0.03138,0.044823 -0.0912,0.039056 -0.284572,-0.027436 C 9.960238,4.7820651 9.5540953,4.716874 8.7838614,4.7156587 8.1159788,4.714605 8.0147273,4.7248012 7.7861458,4.8161304 7.4692447,4.9427474 7.1537943,5.2158239 7.0307038,5.470095 6.9557717,5.6248841 6.9369205,5.7497603 6.9372718,6.0890183 6.9381962,6.9815854 7.196787,7.2221711 8.896851,7.9121547 c 1.770157,0.7184313 2.235733,1.0646714 2.496612,1.8566827 0.135073,0.4100736 0.160583,0.8245586 0.07556,1.2276166 -0.219305,1.039583 -0.982164,1.70704 -2.2361042,1.956462 -0.432887,0.08611 -1.4316239,0.121421 -1.9677294,0.06958 l 0,0 z"
- id="path3780"
+ d="M 8.7838614,11.192151 8.4910396,10.824604 8.1652213,10.7955 C 7.9860213,10.77949 7.7372557,10.74189 7.6124088,10.71194 7.4282733,10.66777 7.37071,10.66881 7.3075341,10.71744 7.2647001,10.75042 7.0725433,10.906338 6.8805198,11.063921 L 6.5313861,11.350448 6.5303212,10.794704 6.5292562,10.23896 6.3457643,10.103812 C 6.2448437,10.02948 6.0928623,9.8921207 6.0080277,9.7985686 L 5.8537831,9.6284734 5.550629,9.6537106 C 5.3838943,9.6675912 5.1505488,9.6891672 5.0320834,9.7016577 L 4.8166919,9.7243676 5.1089758,9.2833964 5.4012598,8.8424258 5.313105,8.5280541 C 5.2646201,8.3551498 5.2248953,8.1422909 5.2248279,8.0550344 5.2247109,7.9035805 5.2043329,7.8832264 4.7754591,7.6061923 4.5283736,7.4465857 4.3369105,7.3053007 4.3499855,7.2922256 4.3630605,7.2791507 4.5804807,7.1951806 4.8331415,7.1056255 L 5.2925247,6.9427982 5.5015381,6.5221912 5.7105514,6.1015842 5.5119451,5.6275414 C 5.4027116,5.3668178 5.3187917,5.139493 5.3254565,5.122375 5.3321213,5.105257 5.5762848,5.1580642 5.8680421,5.2397242 L 6.39851,5.388197 6.6436594,5.2405758 C 6.7784915,5.1593841 6.9462973,5.069142 7.016561,5.0400378 7.1329846,4.9918136 7.1560028,4.9413385 7.276134,4.4708377 7.3486354,4.1868819 7.4218322,3.9545544 7.4387935,3.9545544 c 0.016961,0 0.167268,0.1795652 0.3340147,0.3990338 L 8.075984,4.7526219 8.526434,4.7800645 8.9768837,4.8075071 9.3829946,4.46866 C 9.682759,4.218545 9.7988682,4.1452058 9.8263876,4.1885946 c 0.020505,0.03233 0.037593,0.2632028 0.037972,0.513051 l 6.897e-4,0.4542694 0.2365097,0.1630385 c 0.130081,0.089671 0.324045,0.2523221 0.431032,0.3614465 l 0.194522,0.1984079 0.424909,-0.022226 c 0.2337,-0.012224 0.424909,-0.00908 0.424909,0.00698 0,0.016062 -0.09468,0.1715942 -0.210408,0.3456278 l -0.210409,0.3164248 0.09885,0.302466 c 0.05437,0.1663563 0.111679,0.4118242 0.127355,0.5454842 l 0.0285,0.2430182 0.35335,0.224907 c 0.194343,0.1236989 0.353351,0.2397655 0.353351,0.2579257 0,0.01816 -0.167246,0.093703 -0.371659,0.1678738 l -0.371658,0.1348551 -0.11775,0.3183368 c -0.114487,0.3095158 -0.308347,0.6831506 -0.425566,0.8202137 -0.04785,0.055953 -0.03221,0.1334294 0.09096,0.450495 0.08181,0.210607 0.142539,0.389868 0.134949,0.39836 -0.0076,0.0085 -0.198987,-0.03784 -0.425326,-0.102953 l -0.411526,-0.118393 -0.2562858,0.155382 c -0.1409576,0.08546 -0.342232,0.189654 -0.4472767,0.231542 -0.2055947,0.08199 -0.1835916,0.03825 -0.3508892,0.697448 -0.040873,0.161052 -0.077578,0.29604 -0.081564,0.299973 -0.00399,0.0039 -0.1390187,-0.158245 -0.3000707,-0.360396 l 0,0 z"
+ id="path3693"
+ style="fill:#ffff00"
inkscape:connector-curvature="0" />
</g>
</svg>
diff --git a/setup.py b/setup.py
index df4ce0d..2dbd173 100644
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,10 @@
-import os
-os.system("find ./ | sed 's,^./,ImageProcessor.activity/,g' > MANIFEST")
-os.chdir('..')
-os.system('zip -r ImageProcessor.xo ImageProcessor.activity')
-os.system('mv ImageProcessor.xo ./ImageProcessor.activity')
-os.chdir('ImageProcessor.activity')
+#import os
+#os.system("find ./ | sed 's,^./,ImageProcessor.activity/,g' > MANIFEST")
+#os.chdir('..')
+#os.system('zip -r ImageProcessor.xo ImageProcessor.activity')
+#os.system('mv ImageProcessor.xo ./ImageProcessor.activity')
+#os.chdir('ImageProcessor.activity')
+
+#!/usr/bin/env python
+from sugar.activity import bundlebuilder
+bundlebuilder.start()
diff --git a/toolbar.py b/toolbar.py
index e0bf81c..d08f886 100644
--- a/toolbar.py
+++ b/toolbar.py
@@ -60,7 +60,13 @@ class ViewToolbar(gtk.Toolbar):
'rotate_anticlockwise': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
([])),
- 'copy': (gobject.SIGNAL_RUN_FIRST,
+ 'undo': (gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE,
+ ([])),
+ 'redo': (gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE,
+ ([])),
+ 'save': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
([])),
'paste': (gobject.SIGNAL_RUN_FIRST,
@@ -116,17 +122,32 @@ class ViewToolbar(gtk.Toolbar):
self.insert(rotate_clockwise_button, -1)
rotate_clockwise_button.show()
- copy_button = ToolButton('copy')
- copy_button.set_tooltip(_('copy image'))
- copy_button.connect('clicked', self.copy_cb)
- self.insert(copy_button, -1)
- copy_button.show()
+ self.undo_button = ToolButton('undo')
+ self.undo_button.set_tooltip(_('undo'))
+ self.undo_button.connect('clicked', self.undo_cb)
+ self.insert(self.undo_button, -1)
+ self.undo_button.show()
+
+ self.redo_button = ToolButton('redo')
+ self.redo_button.set_tooltip(_('redo'))
+ self.redo_button.connect('clicked', self.redo_cb)
+ self.insert(self.redo_button, -1)
+ self.redo_button.show()
+
+
+ self.save_button = ToolButton('copy')
+ self.save_button.set_tooltip(_('save image'))
+ self.save_button.connect('clicked', self.save_cb)
+ self.insert(self.save_button, -1)
+ self.save_button.show()
+
+
+ self.paste_button = ToolButton('paste')
+ self.paste_button.set_tooltip(_('paste back saved'))
+ self.paste_button.connect('clicked', self.paste_cb)
+ self.insert(self.paste_button, -1)
+ self.paste_button.show()
- paste_button = ToolButton('paste')
- paste_button.set_tooltip(_('get back copied'))
- paste_button.connect('clicked', self.paste_cb)
- self.insert(paste_button, -1)
- paste_button.show()
def zoom_in_cb(self, button):
self.emit('zoom_in')
@@ -142,8 +163,12 @@ class ViewToolbar(gtk.Toolbar):
self.emit('rotate_clockwise')
def rotate_anticlockwise_cb(self, button):
self.emit('rotate_anticlockwise')
- def copy_cb(self, button):
- self.emit('copy')
+ def undo_cb(self, button):
+ self.emit('undo')
+ def redo_cb(self, button):
+ self.emit('redo')
+ def save_cb(self, button):
+ self.emit('save')
def paste_cb(self, button):
self.emit('paste')
@@ -227,43 +252,43 @@ class EditToolbar(gtk.Toolbar):
self.blur.show()
self.left_top = ToolButton('left_top')
- self.left_top.set_tooltip(_('left_top'))
+ self.left_top.set_tooltip(_('mark text left top'))
self.left_top.connect('clicked', self.left_top_cb)
self.insert(self.left_top, -1)
self.left_top.show()
self.right_top = ToolButton('right_top')
- self.right_top.set_tooltip(_('right_top'))
+ self.right_top.set_tooltip(_('mark text right top'))
self.right_top.connect('clicked', self.right_top_cb)
self.insert(self.right_top, -1)
self.right_top.show()
self.left_bottom = ToolButton('left_bottom')
- self.left_bottom.set_tooltip(_('left_bottom'))
+ self.left_bottom.set_tooltip(_('mark text left bottom'))
self.left_bottom.connect('clicked', self.left_bottom_cb)
self.insert(self.left_bottom, -1)
self.left_bottom.show()
self.right_bottom = ToolButton('right_bottom')
- self.right_bottom.set_tooltip(_('right_bottom'))
+ self.right_bottom.set_tooltip(_('mark text right bottom'))
self.right_bottom.connect('clicked', self.right_bottom_cb)
self.insert(self.right_bottom, -1)
self.right_bottom.show()
self.watermark_tl = ToolButton('watermark_tl')
- self.watermark_tl.set_tooltip(_('watermark top left'))
+ self.watermark_tl.set_tooltip(_('mark image top left'))
self.watermark_tl.connect('clicked', self.watermark_tl_cb)
self.insert(self.watermark_tl, -1)
self.watermark_tl.show()
self.watermark_til = ToolButton('watermark_tile')
- self.watermark_til.set_tooltip(_('watermark tile form'))
+ self.watermark_til.set_tooltip(_('mark image tile form'))
self.watermark_til.connect('clicked', self.watermark_tile_cb)
self.insert(self.watermark_til, -1)
self.watermark_til.show()
self.watermark_scale = ToolButton('watermark_scale')
- self.watermark_scale.set_tooltip(_('watermark scale form'))
+ self.watermark_scale.set_tooltip(_('mark scale form'))
self.watermark_scale.connect('clicked', self.watermark_scale_cb)
self.insert(self.watermark_scale, -1)
self.watermark_scale.show()