Browse Source

--- Merging r21483 into '.':
U packages/fcl-image/src/fpreadtiff.pas
U packages/fcl-image/src/fptiffcmn.pas
U packages/fcl-image/src/fpwritetiff.pas
--- Merging r21485 into '.':
G packages/fcl-image/src/fpreadtiff.pas
G packages/fcl-image/src/fptiffcmn.pas
G packages/fcl-image/src/fpwritetiff.pas
--- Merging r21489 into '.':
G packages/fcl-image/src/fpreadtiff.pas
G packages/fcl-image/src/fptiffcmn.pas
G packages/fcl-image/src/fpwritetiff.pas
--- Merging r21494 into '.':
G packages/fcl-image/src/fpwritetiff.pas
--- Merging r21514 into '.':
G packages/fcl-image/src/fpreadtiff.pas
--- Merging r21517 into '.':
G packages/fcl-image/src/fpreadtiff.pas
G packages/fcl-image/src/fptiffcmn.pas
G packages/fcl-image/src/fpwritetiff.pas
--- Merging r21549 into '.':
G packages/fcl-image/src/fpreadtiff.pas
G packages/fcl-image/src/fptiffcmn.pas
G packages/fcl-image/src/fpwritetiff.pas
--- Merging r21638 into '.':
U packages/fcl-image/src/fpwritepng.pp
--- Merging r21639 into '.':
U packages/fcl-image/src/fpinterpolation.inc
A packages/fcl-image/examples/interpoldemo.pp
U packages/fcl-image/examples/Makefile.fpc
C packages/fcl-image/examples/Makefile
--- Merging r21653 into '.':
U packages/fcl-image/fpmake.pp
U packages/fcl-image/src/fpimage.pp
U packages/fcl-image/examples/drawing.pp
--- Merging r21654 into '.':
A packages/fcl-image/src/fpcompactimg.inc
--- Merging r21655 into '.':
G packages/fcl-image/fpmake.pp
A packages/fcl-image/src/fpimggauss.pp
--- Merging r22001 into '.':
G packages/fcl-image/src/fpreadtiff.pas
Summary of conflicts:
Text conflicts: 1

# revisions: 21483,21485,21489,21494,21514,21517,21549,21638,21639,21653,21654,21655,22001
r21483 | mattias | 2012-06-04 11:39:09 +0200 (Mon, 04 Jun 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-image/src/fpreadtiff.pas
M /trunk/packages/fcl-image/src/fptiffcmn.pas
M /trunk/packages/fcl-image/src/fpwritetiff.pas

fcl-image: tiff: reading CMYK, handling of unorderd tags, alpha mode 1, multiple pages, tiles
r21485 | mattias | 2012-06-04 19:09:38 +0200 (Mon, 04 Jun 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-image/src/fpreadtiff.pas
M /trunk/packages/fcl-image/src/fptiffcmn.pas
M /trunk/packages/fcl-image/src/fpwritetiff.pas

fcl-image: tiff: register handler, write hostname, maker, model, software
r21489 | mattias | 2012-06-05 20:33:33 +0200 (Tue, 05 Jun 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-image/src/fpreadtiff.pas
M /trunk/packages/fcl-image/src/fptiffcmn.pas
M /trunk/packages/fcl-image/src/fpwritetiff.pas

fpimage: tiff: write tiles
r21494 | mattias | 2012-06-06 02:01:41 +0200 (Wed, 06 Jun 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-image/src/fpwritetiff.pas

fpimage: tiff: fixed writing bits per channel
r21514 | mattias | 2012-06-07 18:09:33 +0200 (Thu, 07 Jun 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-image/src/fpreadtiff.pas

tiff: fixed decompressing packbits, skip jpeg tags
r21517 | mattias | 2012-06-07 19:23:16 +0200 (Thu, 07 Jun 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-image/src/fpreadtiff.pas
M /trunk/packages/fcl-image/src/fptiffcmn.pas
M /trunk/packages/fcl-image/src/fpwritetiff.pas

fcl-image: tiff: read/write PageName, fixed typos
r21549 | mattias | 2012-06-08 13:56:05 +0200 (Fri, 08 Jun 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-image/src/fpreadtiff.pas
M /trunk/packages/fcl-image/src/fptiffcmn.pas
M /trunk/packages/fcl-image/src/fpwritetiff.pas

fcl-image: tiff: reader+writer: deflate compression
r21638 | marco | 2012-06-18 09:50:18 +0200 (Mon, 18 Jun 2012) | 3 lines
Changed paths:
M /trunk/packages/fcl-image/src/fpwritepng.pp

* Zero header before filling it. Colortype and potentially other fields
were not properly initialized in non indexed files. Mantis #21840
r21639 | marco | 2012-06-18 11:01:41 +0200 (Mon, 18 Jun 2012) | 2 lines
Changed paths:
M /trunk/packages/fcl-image/examples/Makefile
M /trunk/packages/fcl-image/examples/Makefile.fpc
A /trunk/packages/fcl-image/examples/interpoldemo.pp
M /trunk/packages/fcl-image/src/fpinterpolation.inc

* Fix scaling with alpha channel. Patch from Bernd Kreuss, Mantis #22245
* Demo that demonstrates image scaling/interpolation
r21653 | michael | 2012-06-19 20:25:27 +0200 (Tue, 19 Jun 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-image/examples/drawing.pp
M /trunk/packages/fcl-image/fpmake.pp
M /trunk/packages/fcl-image/src/fpimage.pp

* Added compact image support by Mattias Gaertner
r21654 | michael | 2012-06-19 20:25:47 +0200 (Tue, 19 Jun 2012) | 1 line
Changed paths:
A /trunk/packages/fcl-image/src/fpcompactimg.inc

* Added compact image support by Mattias Gaertner
r21655 | michael | 2012-06-19 20:38:47 +0200 (Tue, 19 Jun 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-image/fpmake.pp
A /trunk/packages/fcl-image/src/fpimggauss.pp

* Added fpimggauss.pp unit from Mattias Gaertner
r22001 | marco | 2012-08-03 14:24:11 +0200 (Fri, 03 Aug 2012) | 2 lines
Changed paths:
M /trunk/packages/fcl-image/src/fpreadtiff.pas

* fixed a copy and paste typo as indicated by Ocean Mantis #22559

git-svn-id: branches/fixes_2_6@22295 -

marco 13 years ago
parent
commit
83efa43bfb

+ 3 - 0
.gitattributes

@@ -2089,6 +2089,7 @@ packages/fcl-image/examples/Makefile svneol=native#text/plain
 packages/fcl-image/examples/Makefile.fpc svneol=native#text/plain
 packages/fcl-image/examples/drawing.pp svneol=native#text/plain
 packages/fcl-image/examples/imgconv.pp svneol=native#text/plain
+packages/fcl-image/examples/interpoldemo.pp svneol=native#text/plain
 packages/fcl-image/examples/xwdtobmp.pas svneol=native#text/plain
 packages/fcl-image/fpmake.pp svneol=native#text/plain
 packages/fcl-image/src/bmpcomn.pp svneol=native#text/plain
@@ -2102,6 +2103,7 @@ packages/fcl-image/src/fpcdrawh.inc svneol=native#text/plain
 packages/fcl-image/src/fpcolcnv.inc svneol=native#text/plain
 packages/fcl-image/src/fpcolhash.pas svneol=native#text/plain
 packages/fcl-image/src/fpcolors.inc svneol=native#text/plain
+packages/fcl-image/src/fpcompactimg.inc svneol=native#text/plain
 packages/fcl-image/src/fpditherer.pas svneol=native#text/plain
 packages/fcl-image/src/fpfont.inc svneol=native#text/plain
 packages/fcl-image/src/fphandler.inc svneol=native#text/plain
@@ -2110,6 +2112,7 @@ packages/fcl-image/src/fpimage.inc svneol=native#text/plain
 packages/fcl-image/src/fpimage.pp svneol=native#text/plain
 packages/fcl-image/src/fpimgcanv.pp svneol=native#text/plain
 packages/fcl-image/src/fpimgcmn.pp svneol=native#text/plain
+packages/fcl-image/src/fpimggauss.pp svneol=native#text/plain
 packages/fcl-image/src/fpinterpolation.inc svneol=native#text/plain
 packages/fcl-image/src/fppalette.inc svneol=native#text/plain
 packages/fcl-image/src/fppen.inc svneol=native#text/plain

+ 66 - 66
packages/fcl-image/Makefile

@@ -1,5 +1,5 @@
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2012/08/21]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2012/06/26]
 #
 default: all
 MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent i386-iphonesim m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded powerpc-wii sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-netbsd x86_64-solaris x86_64-openbsd x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded mipsel-linux
@@ -289,199 +289,199 @@ endif
 override PACKAGE_NAME=fcl-image
 override PACKAGE_VERSION=2.6.1
 ifeq ($(FULL_TARGET),i386-linux)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),i386-os2)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),i386-beos)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),i386-haiku)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),i386-solaris)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),i386-qnx)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),i386-netware)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),i386-wdosx)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),i386-darwin)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),i386-emx)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),i386-wince)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),i386-embedded)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),i386-symbian)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),i386-nativent)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),i386-iphonesim)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),m68k-freebsd)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),m68k-amiga)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),m68k-palmos)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),m68k-embedded)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),powerpc-amiga)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),powerpc-morphos)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),powerpc-embedded)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),powerpc-wii)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),sparc-solaris)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),sparc-embedded)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),x86_64-netbsd)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),x86_64-solaris)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),x86_64-openbsd)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),x86_64-win64)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),arm-palmos)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),arm-darwin)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),arm-wince)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),arm-gba)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),arm-nds)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),arm-embedded)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),arm-symbian)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),powerpc64-darwin)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),powerpc64-embedded)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),avr-embedded)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),armeb-linux)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),armeb-embedded)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 endif
 ifeq ($(FULL_TARGET),mipsel-linux)
-override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd  freetypeh freetype ftfont
+override TARGET_UNITS+=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm clipping fpcanvas pixtools fppixlcanv fpimgcanv pscanvas fpwritebmp fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss  freetypeh freetype ftfont
 endif
 ifeq ($(FULL_TARGET),i386-linux)
 override TARGET_RSTS+=pscanvas

+ 1 - 1
packages/fcl-image/Makefile.fpc

@@ -12,7 +12,7 @@ units=fpimgcmn fpimage pngcomn fpreadpng fpwritepng fpreadxpm fpwritexpm \
       fpreadbmp bmpcomn fpreadpnm fpwritepnm fpreadjpeg fpwritejpeg \
       pcxcomn fpreadpcx fpwritepcx fptiffcmn fpreadtiff fpwritetiff \
       targacmn fpreadtga fpwritetga ellipses fpcolhash fpditherer fpquantizer \ 
-      extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd
+      extinterpolation fpreadgif fpreadpsd xwdfile fpreadxwd fpimggauss
 units_win32=freetypeh freetype ftfont
 units_win64=freetypeh freetype ftfont
 units_beos=freetypeh freetype ftfont

+ 87 - 65
packages/fcl-image/examples/Makefile

@@ -1,8 +1,8 @@
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2011/12/30]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2012/06/26]
 #
 default: all
-MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent i386-iphonesim m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded powerpc-wii sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-solaris x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded mipsel-linux
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent i386-iphonesim m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded powerpc-wii sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-netbsd x86_64-solaris x86_64-openbsd x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded mipsel-linux
 BSDs = freebsd netbsd openbsd darwin
 UNIXs = linux $(BSDs) solaris qnx haiku
 LIMIT83fs = go32v2 os2 emx watcom
@@ -287,193 +287,199 @@ FPCFPMAKE=$(FPC)
 endif
 endif
 ifeq ($(FULL_TARGET),i386-linux)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-os2)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-beos)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-haiku)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-solaris)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-qnx)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-netware)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-wdosx)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-darwin)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-emx)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-wince)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-embedded)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-symbian)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-nativent)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),i386-iphonesim)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),m68k-freebsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),m68k-amiga)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),m68k-palmos)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),m68k-embedded)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),powerpc-amiga)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),powerpc-morphos)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),powerpc-embedded)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),powerpc-wii)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),sparc-solaris)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),sparc-embedded)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
+endif
+ifeq ($(FULL_TARGET),x86_64-netbsd)
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),x86_64-solaris)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
+endif
+ifeq ($(FULL_TARGET),x86_64-openbsd)
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),x86_64-win64)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),arm-palmos)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),arm-darwin)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),arm-wince)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),arm-gba)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),arm-nds)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),arm-embedded)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),arm-symbian)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),powerpc64-darwin)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),powerpc64-embedded)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),avr-embedded)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),armeb-linux)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),armeb-embedded)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 ifeq ($(FULL_TARGET),mipsel-linux)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
 endif
 override INSTALL_FPCPACKAGE=y
 ifdef REQUIRE_UNITSDIR
@@ -1425,6 +1431,14 @@ REQUIRE_PACKAGES_PASZLIB=1
 REQUIRE_PACKAGES_FCL-BASE=1
 REQUIRE_PACKAGES_FCL-IMAGE=1
 endif
+ifeq ($(FULL_TARGET),x86_64-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASJPEG=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-IMAGE=1
+endif
 ifeq ($(FULL_TARGET),x86_64-solaris)
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_PASJPEG=1
@@ -1433,6 +1447,14 @@ REQUIRE_PACKAGES_PASZLIB=1
 REQUIRE_PACKAGES_FCL-BASE=1
 REQUIRE_PACKAGES_FCL-IMAGE=1
 endif
+ifeq ($(FULL_TARGET),x86_64-openbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASJPEG=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-IMAGE=1
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_PASJPEG=1

+ 1 - 1
packages/fcl-image/examples/Makefile.fpc

@@ -3,7 +3,7 @@
 #
 
 [target]
-programs=imgconv drawing xwdtobmp
+programs=imgconv drawing xwdtobmp interpoldemo
 
 [require]
 packages=fcl-image

+ 18 - 4
packages/fcl-image/examples/drawing.pp

@@ -2,7 +2,7 @@
 program Drawing;
 
 uses classes, sysutils,
-     FPImage, FPCanvas, FPImgCanv,
+     FPImage, FPCanvas, FPImgCanv, ftFont,
      FPWritePNG, FPReadPNG;
 
 const
@@ -13,6 +13,7 @@ var canvas : TFPcustomCAnvas;
     ci, image : TFPCustomImage;
     writer : TFPCustomImageWriter;
     reader : TFPCustomImageReader;
+    f : TFreeTypeFont;
 begin
   image := TFPMemoryImage.Create (100,100);
   ci := TFPMemoryImage.Create (20,20);
@@ -27,7 +28,7 @@ begin
     GrayScale := false;
     end;
   try
-    ci.LoadFromFile ('test.png', reader);
+//    ci.LoadFromFile ('test.png', reader);
     with Canvas as TFPImageCanvas do
       begin
       pen.mode := pmCopy;
@@ -51,11 +52,13 @@ begin
         end;
       pen.style := psSolid;
       RelativeBrushImage := true;
+{
       brush.image := ci;
       brush.style := bsimage;
       with brush.FPColor do
         green := green div 2;
       Ellipse (11,11, 89,89);
+}
 
       brush.style := bsSolid;
       brush.FPColor := MyColor;
@@ -68,8 +71,19 @@ begin
       pen.FPColor := colCyan;
       ellipseC (50,50, 1,1);
 
-      writeln ('Saving to inspect !');
+      InitEngine;
+      F:=TFreeTypeFont.Create;
+      F.Angle:=0.15;
+      Font:=F;
+//      Font.Name:='/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf';
+      Font.Name:='/home/michael/Documents/arial.ttf';
+      Font.Size:=10;
+      Font.FPColor:=colWhite;
+//      Font.Orientation:=900;
+      
+      Canvas.TextOut(10,90,'o');
       end;
+      writeln ('Saving to inspect !');
     image.SaveToFile ('DrawTest.png', writer);
   finally
     Canvas.Free;
@@ -81,7 +95,7 @@ begin
 end;
 
 begin
-  // DefaultFontPath := 'c:\winnt\fonts\';
+//  DefaultFontPath := '/usr/share/fonts/truetype/ttf-dejavu/';
   DoDraw;
 
 end.

+ 39 - 0
packages/fcl-image/examples/interpoldemo.pp

@@ -0,0 +1,39 @@
+program interpoldemo;
+// Interpolation demo for fcl-image by Bernd Kreuss. Mantis #22245
+// Loads original.png (not included) and scales it back to 64x64
+
+{$mode objfpc}{$H+}
+
+uses
+  Classes,
+  sysutils,
+  FPimage,
+  FPImgCanv,
+  FPReadPNG,
+  FPWritePNG;
+
+var
+  ImOriginal: TFPMemoryImage;
+  ImScaled: TFPMemoryImage;
+  CanvScaled: TFPImageCanvas;
+  Reader: TFPReaderPNG;
+  Writer: TFPWriterPNG;
+
+begin
+  ImOriginal := TFPMemoryImage.Create(0, 0);
+  ImScaled := TFPMemoryImage.Create(64, 64);
+  Reader := TFPReaderPNG.create;
+  Writer := TFPWriterPNG.create;
+  Writer.UseAlpha := True;
+  ImOriginal.LoadFromFile('original.png', Reader);
+
+  CanvScaled := TFPImageCanvas.create(ImScaled);
+  CanvScaled.StretchDraw(0,0,63,63, ImOriginal);
+
+  ImScaled.SaveToFile('scaled.png', Writer);
+  Reader.Free;
+  Writer.Free;
+  ImOriginal.Free;
+  ImScaled.Free;
+end.
+

+ 5 - 1
packages/fcl-image/fpmake.pp

@@ -86,6 +86,7 @@ begin
           AddInclude('fphandler.inc');
           AddInclude('fppalette.inc');
           AddInclude('fpcolcnv.inc');
+          AddInclude('fpcompactimg.inc');
         end;
     T:=P.Targets.AddUnit('fpimgcanv.pp');
       with T.Dependencies do
@@ -259,7 +260,10 @@ begin
           AddUnit('fpcanvas');
         end;
     T:=P.Targets.AddUnit('targacmn.pp');
-
+    T:=P.Targets.AddUnit('fpimggauss.pp');
+    With T.Dependencies do
+      AddUnit('fpimage'); 
+                  
     P.ExamplePath.Add('examples');
     T:=P.Targets.AddExampleProgram('drawing.pp');
     T:=P.Targets.AddExampleProgram('imgconv.pp');

+ 597 - 0
packages/fcl-image/src/fpcompactimg.inc

@@ -0,0 +1,597 @@
+{%MainUnit fpimage.pp}
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by the Free Pascal development team
+       
+    Compact images (images with less than 64-bit depth) support, by Mattias Gaertner
+           
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+    
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+    
+ **********************************************************************}
+
+function GetFPCompactImgDesc(Gray: boolean; Depth: word; HasAlpha: boolean
+  ): TFPCompactImgDesc;
+begin
+  Result.Gray:=Gray;
+  Result.Depth:=Depth;
+  Result.HasAlpha:=HasAlpha;
+end;
+
+function GetFPCompactImgClass(const Desc: TFPCompactImgDesc): TFPCompactImgBaseClass;
+begin
+  if Desc.Gray then begin
+    if Desc.HasAlpha then begin
+      // gray, alpha
+      if Desc.Depth<=8 then
+        Result:=TFPCompactImgGrayAlpha8Bit
+      else
+        Result:=TFPCompactImgGrayAlpha16Bit;
+    end else begin
+      // gray, no alpha
+      if Desc.Depth<=8 then
+        Result:=TFPCompactImgGray8Bit
+      else
+        Result:=TFPCompactImgGray16Bit;
+    end;
+  end else begin
+    // RGB
+    if Desc.HasAlpha then begin
+      // RGB, alpha
+      if Desc.Depth<=8 then
+        Result:=TFPCompactImgRGBA8Bit
+      else
+        Result:=TFPCompactImgRGBA16Bit;
+    end else begin
+      // RGB, no alpha
+      if Desc.Depth<=8 then
+        Result:=TFPCompactImgRGB8Bit
+      else
+        Result:=TFPCompactImgRGB16Bit;
+    end;
+  end;
+end;
+
+function CreateFPCompactImg(const Desc: TFPCompactImgDesc; Width, Height: integer
+  ): TFPCustomImage;
+var
+  ImgClass: TFPCompactImgBaseClass;
+begin
+  ImgClass:=GetFPCompactImgClass(Desc);
+  Result:=ImgClass.Create(Width,Height);
+end;
+
+function CreateCompatibleFPCompactImg(Img: TFPCustomImage; Width, Height: integer
+  ): TFPCustomImage;
+begin
+  if Img is TFPCompactImgBase then
+    Result:=CreateFPCompactImg(TFPCompactImgBase(Img).Desc,Width,Height)
+  else
+    Result:=CreateFPCompactImg(GetMinimumPTDesc(Img),Width,Height);
+end;
+
+function CreateCompatibleFPCompactImgWithAlpha(Img: TFPCustomImage; Width,
+  Height: integer): TFPCustomImage;
+var
+  Desc: TFPCompactImgDesc;
+begin
+  if Img is TFPCompactImgBase then
+    Desc:=TFPCompactImgBase(Img).Desc
+  else
+    Desc:=GetMinimumPTDesc(Img);
+  Desc.HasAlpha:=true;
+  Result:=CreateFPCompactImg(Desc,Width,Height);
+end;
+
+function GetMinimumPTDesc(Img: TFPCustomImage; FuzzyDepth: word = 4): TFPCompactImgDesc;
+var
+  AllLoEqualsHi, AllLoAre0: Boolean;
+  FuzzyMaskLoHi: Word;
+
+  procedure Need16Bit(c: word); inline;
+  var
+    l: Byte;
+  begin
+    c:=c and FuzzyMaskLoHi;
+    l:=Lo(c);
+    AllLoAre0:=AllLoAre0 and (l=0);
+    AllLoEqualsHi:=AllLoEqualsHi and (l=Hi(c));
+  end;
+
+var
+  TestGray: Boolean;
+  TestAlpha: Boolean;
+  Test16Bit: Boolean;
+  BaseImg: TFPCompactImgBase;
+  ImgDesc: TFPCompactImgDesc;
+  y: Integer;
+  x: Integer;
+  col: TFPColor;
+  FuzzyMaskWord: Word;
+  FuzzyOpaque: Word;
+begin
+  TestGray:=true;
+  TestAlpha:=true;
+  Test16Bit:=FuzzyDepth<8;
+  Result.HasAlpha:=false;
+  Result.Gray:=true;
+  Result.Depth:=8;
+  if Img is TFPCompactImgBase then begin
+    BaseImg:=TFPCompactImgBase(Img);
+    ImgDesc:=BaseImg.Desc;
+    if ImgDesc.Depth<=8 then Test16Bit:=false;
+    if ImgDesc.Gray then TestGray:=false;
+    if not ImgDesc.HasAlpha then TestAlpha:=false;
+  end;
+
+  if (not TestGray) and (not TestAlpha) and (not Test16Bit) then exit;
+
+  FuzzyMaskWord:=Word($ffff) shl FuzzyDepth;
+  FuzzyOpaque:=alphaOpaque and FuzzyMaskWord;
+  FuzzyMaskLoHi:=Word(lo(FuzzyMaskWord))+(Word(lo(FuzzyMaskWord)) shl 8);
+  AllLoAre0:=true;
+  AllLoEqualsHi:=true;
+  for y:=0 to Img.Height-1 do begin
+    for x:=0 to Img.Width-1 do begin
+      col:=Img.Colors[x,y];
+      if TestAlpha and ((col.alpha and FuzzyMaskWord)<>FuzzyOpaque) then begin
+        TestAlpha:=false;
+        Result.HasAlpha:=true;
+        if (not TestGray) and (not Test16Bit) then break;
+      end;
+      if TestGray
+      and ((col.red and FuzzyMaskWord)<>(col.green and FuzzyMaskWord))
+      or ((col.red and FuzzyMaskWord)<>(col.blue and FuzzyMaskWord)) then begin
+        TestGray:=false;
+        Result.Gray:=false;
+        if (not TestAlpha) and (not Test16Bit) then break;
+      end;
+      if Test16Bit then begin
+        Need16Bit(col.red);
+        Need16Bit(col.green);
+        Need16Bit(col.blue);
+        Need16Bit(col.alpha);
+        if (not AllLoAre0) and (not AllLoEqualsHi) then begin
+          Test16Bit:=false;
+          Result.Depth:=16;
+          if (not TestAlpha) and (not TestGray) then break;
+        end;
+      end;
+    end;
+  end;
+end;
+
+function GetMinimumFPCompactImg(Img: TFPCustomImage; FreeImg: boolean;
+  FuzzyDepth: word = 4): TFPCustomImage;
+var
+  Desc: TFPCompactImgDesc;
+  ImgClass: TFPCompactImgBaseClass;
+  y: Integer;
+  x: Integer;
+begin
+  Desc:=GetMinimumPTDesc(Img,FuzzyDepth);
+  ImgClass:=GetFPCompactImgClass(Desc);
+  if Img.ClassType=ImgClass then
+    exit(Img);
+  Result:=CreateFPCompactImg(Desc,Img.Width,Img.Height);
+  for y:=0 to Img.Height-1 do
+    for x:=0 to Img.Width-1 do
+      Result.Colors[x,y]:=Img.Colors[x,y];
+  if FreeImg then
+    Img.Free;
+end;
+
+function ColorRound (c : double) : word;
+begin
+  if c > $FFFF then
+    result := $FFFF
+  else if c < 0.0 then
+    result := 0
+  else
+    result := round(c);
+end;
+
+{ TFPCompactImgGrayAlpha16Bit }
+
+function TFPCompactImgGrayAlpha16Bit.GetInternalColor(x, y: integer): TFPColor;
+var
+  v: TFPCompactImgGrayAlpha16BitValue;
+begin
+  v:=FData[x+y*Width];
+  Result.red:=v.g;
+  Result.green:=Result.red;
+  Result.blue:=Result.red;
+  Result.alpha:=v.a;
+end;
+
+function TFPCompactImgGrayAlpha16Bit.GetInternalPixel(x, y: integer): integer;
+begin
+  Result:=0;
+end;
+
+procedure TFPCompactImgGrayAlpha16Bit.SetInternalColor(x, y: integer;
+  const Value: TFPColor);
+var
+  v: TFPCompactImgGrayAlpha16BitValue;
+begin
+  v.g:=Value.red;
+  v.a:=Value.alpha;
+  FData[x+y*Width]:=v;
+end;
+
+procedure TFPCompactImgGrayAlpha16Bit.SetInternalPixel(x, y: integer; Value: integer
+  );
+begin
+
+end;
+
+constructor TFPCompactImgGrayAlpha16Bit.Create(AWidth, AHeight: integer);
+begin
+  FDesc:=GetFPCompactImgDesc(true,16,true);
+  inherited Create(AWidth, AHeight);
+end;
+
+destructor TFPCompactImgGrayAlpha16Bit.Destroy;
+begin
+  ReAllocMem(FData,0);
+  inherited Destroy;
+end;
+
+procedure TFPCompactImgGrayAlpha16Bit.SetSize(AWidth, AHeight: integer);
+begin
+  if (AWidth=Width) and (AHeight=Height) then exit;
+  ReAllocMem(FData,SizeOf(TFPCompactImgGrayAlpha16BitValue)*AWidth*AHeight);
+  inherited SetSize(AWidth, AHeight);
+end;
+
+{ TFPCompactImgGrayAlpha8Bit }
+
+function TFPCompactImgGrayAlpha8Bit.GetInternalColor(x, y: integer): TFPColor;
+var
+  v: TFPCompactImgGrayAlpha8BitValue;
+begin
+  v:=FData[x+y*Width];
+  Result.red:=(v.g shl 8)+v.g;
+  Result.green:=Result.red;
+  Result.blue:=Result.red;
+  Result.alpha:=(v.a shl 8)+v.a;
+end;
+
+function TFPCompactImgGrayAlpha8Bit.GetInternalPixel(x, y: integer): integer;
+begin
+  Result:=0;
+end;
+
+procedure TFPCompactImgGrayAlpha8Bit.SetInternalColor(x, y: integer;
+  const Value: TFPColor);
+var
+  v: TFPCompactImgGrayAlpha8BitValue;
+begin
+  v.g:=Value.red shr 8;
+  v.a:=Value.alpha shr 8;
+  FData[x+y*Width]:=v;
+end;
+
+procedure TFPCompactImgGrayAlpha8Bit.SetInternalPixel(x, y: integer; Value: integer
+  );
+begin
+
+end;
+
+constructor TFPCompactImgGrayAlpha8Bit.Create(AWidth, AHeight: integer);
+begin
+  FDesc:=GetFPCompactImgDesc(true,8,true);
+  inherited Create(AWidth, AHeight);
+end;
+
+destructor TFPCompactImgGrayAlpha8Bit.Destroy;
+begin
+  ReAllocMem(FData,0);
+  inherited Destroy;
+end;
+
+procedure TFPCompactImgGrayAlpha8Bit.SetSize(AWidth, AHeight: integer);
+begin
+  if (AWidth=Width) and (AHeight=Height) then exit;
+  ReAllocMem(FData,SizeOf(TFPCompactImgGrayAlpha8BitValue)*AWidth*AHeight);
+  inherited SetSize(AWidth, AHeight);
+end;
+
+{ TFPCompactImgGray16Bit }
+
+function TFPCompactImgGray16Bit.GetInternalColor(x, y: integer): TFPColor;
+begin
+  Result.red:=FData[x+y*Width];
+  Result.green:=Result.red;
+  Result.blue:=Result.red;
+  Result.alpha:=alphaOpaque;
+end;
+
+function TFPCompactImgGray16Bit.GetInternalPixel(x, y: integer): integer;
+begin
+  Result:=0;
+end;
+
+procedure TFPCompactImgGray16Bit.SetInternalColor(x, y: integer;
+  const Value: TFPColor);
+begin
+  FData[x+y*Width]:=Value.red;
+end;
+
+procedure TFPCompactImgGray16Bit.SetInternalPixel(x, y: integer; Value: integer);
+begin
+
+end;
+
+constructor TFPCompactImgGray16Bit.Create(AWidth, AHeight: integer);
+begin
+  FDesc:=GetFPCompactImgDesc(true,16,false);
+  inherited Create(AWidth, AHeight);
+end;
+
+destructor TFPCompactImgGray16Bit.Destroy;
+begin
+  ReAllocMem(FData,0);
+  inherited Destroy;
+end;
+
+procedure TFPCompactImgGray16Bit.SetSize(AWidth, AHeight: integer);
+begin
+  if (AWidth=Width) and (AHeight=Height) then exit;
+  ReAllocMem(FData,SizeOf(Word)*AWidth*AHeight);
+  inherited SetSize(AWidth,AHeight);
+end;
+
+{ TFPCompactImgGray8Bit }
+
+function TFPCompactImgGray8Bit.GetInternalColor(x, y: integer): TFPColor;
+begin
+  Result.red:=FData[x+y*Width];
+  Result.red:=(Word(Result.red) shl 8)+Result.red;
+  Result.green:=Result.red;
+  Result.blue:=Result.red;
+  Result.alpha:=alphaOpaque;
+end;
+
+function TFPCompactImgGray8Bit.GetInternalPixel(x, y: integer): integer;
+begin
+  Result:=0;
+end;
+
+procedure TFPCompactImgGray8Bit.SetInternalColor(x, y: integer;
+  const Value: TFPColor);
+begin
+  FData[x+y*Width]:=Value.red shr 8;
+end;
+
+procedure TFPCompactImgGray8Bit.SetInternalPixel(x, y: integer; Value: integer);
+begin
+
+end;
+
+constructor TFPCompactImgGray8Bit.Create(AWidth, AHeight: integer);
+begin
+  FDesc:=GetFPCompactImgDesc(true,8,false);
+  inherited Create(AWidth, AHeight);
+end;
+
+destructor TFPCompactImgGray8Bit.Destroy;
+begin
+  ReAllocMem(FData,0);
+  inherited Destroy;
+end;
+
+procedure TFPCompactImgGray8Bit.SetSize(AWidth, AHeight: integer);
+begin
+  if (AWidth=Width) and (AHeight=Height) then exit;
+  ReAllocMem(FData,SizeOf(Byte)*AWidth*AHeight);
+  inherited SetSize(AWidth,AHeight);
+end;
+
+{ TFPCompactImgRGBA8Bit }
+
+function TFPCompactImgRGBA8Bit.GetInternalColor(x, y: integer): TFPColor;
+var
+  v: TFPCompactImgRGBA8BitValue;
+begin
+  v:=FData[x+y*Width];
+  Result.red:=(v.r shl 8)+v.r;
+  Result.green:=(v.g shl 8)+v.g;
+  Result.blue:=(v.b shl 8)+v.b;
+  Result.alpha:=(v.a shl 8)+v.a;
+end;
+
+function TFPCompactImgRGBA8Bit.GetInternalPixel(x, y: integer): integer;
+begin
+  Result:=0;
+end;
+
+procedure TFPCompactImgRGBA8Bit.SetInternalColor(x, y: integer;
+  const Value: TFPColor);
+var
+  v: TFPCompactImgRGBA8BitValue;
+begin
+  v.r:=Value.red shr 8;
+  v.g:=Value.green shr 8;
+  v.b:=Value.blue shr 8;
+  v.a:=Value.alpha shr 8;
+  FData[x+y*Width]:=v;
+end;
+
+procedure TFPCompactImgRGBA8Bit.SetInternalPixel(x, y: integer; Value: integer);
+begin
+
+end;
+
+constructor TFPCompactImgRGBA8Bit.Create(AWidth, AHeight: integer);
+begin
+  FDesc:=GetFPCompactImgDesc(false,8,true);
+  inherited Create(AWidth, AHeight);
+end;
+
+destructor TFPCompactImgRGBA8Bit.Destroy;
+begin
+  ReAllocMem(FData,0);
+  inherited Destroy;
+end;
+
+procedure TFPCompactImgRGBA8Bit.SetSize(AWidth, AHeight: integer);
+begin
+  if (AWidth=Width) and (AHeight=Height) then exit;
+  ReAllocMem(FData,SizeOf(TFPCompactImgRGBA8BitValue)*AWidth*AHeight);
+  inherited SetSize(AWidth,AHeight);
+end;
+
+{ TFPCompactImgRGB8Bit }
+
+function TFPCompactImgRGB8Bit.GetInternalColor(x, y: integer): TFPColor;
+var
+  v: TFPCompactImgRGB8BitValue;
+begin
+  v:=FData[x+y*Width];
+  Result.red:=(v.r shl 8)+v.r;
+  Result.green:=(v.g shl 8)+v.g;
+  Result.blue:=(v.b shl 8)+v.b;
+  Result.alpha:=alphaOpaque;
+end;
+
+function TFPCompactImgRGB8Bit.GetInternalPixel(x, y: integer): integer;
+begin
+  Result:=0;
+end;
+
+procedure TFPCompactImgRGB8Bit.SetInternalColor(x, y: integer; const Value: TFPColor
+  );
+var
+  v: TFPCompactImgRGB8BitValue;
+begin
+  v.r:=Value.red shr 8;
+  v.g:=Value.green shr 8;
+  v.b:=Value.blue shr 8;
+  FData[x+y*Width]:=v;
+end;
+
+procedure TFPCompactImgRGB8Bit.SetInternalPixel(x, y: integer; Value: integer);
+begin
+
+end;
+
+constructor TFPCompactImgRGB8Bit.Create(AWidth, AHeight: integer);
+begin
+  FDesc:=GetFPCompactImgDesc(false,8,false);
+  inherited Create(AWidth, AHeight);
+end;
+
+destructor TFPCompactImgRGB8Bit.Destroy;
+begin
+  ReAllocMem(FData,0);
+  inherited Destroy;
+end;
+
+procedure TFPCompactImgRGB8Bit.SetSize(AWidth, AHeight: integer);
+begin
+  if (AWidth=Width) and (AHeight=Height) then exit;
+  ReAllocMem(FData,SizeOf(TFPCompactImgRGB8BitValue)*AWidth*AHeight);
+  inherited SetSize(AWidth,AHeight);
+end;
+
+{ TFPCompactImgRGB16Bit }
+
+function TFPCompactImgRGB16Bit.GetInternalColor(x, y: integer): TFPColor;
+var
+  v: TFPCompactImgRGB16BitValue;
+begin
+  v:=FData[x+y*Width];
+  Result.red:=v.r;
+  Result.green:=v.g;
+  Result.blue:=v.b;
+  Result.alpha:=alphaOpaque;
+end;
+
+function TFPCompactImgRGB16Bit.GetInternalPixel(x, y: integer): integer;
+begin
+  Result:=0;
+end;
+
+procedure TFPCompactImgRGB16Bit.SetInternalColor(x, y: integer;
+  const Value: TFPColor);
+var
+  v: TFPCompactImgRGB16BitValue;
+begin
+  v.r:=Value.red;
+  v.g:=Value.green;
+  v.b:=Value.blue;
+  FData[x+y*Width]:=v;
+end;
+
+procedure TFPCompactImgRGB16Bit.SetInternalPixel(x, y: integer; Value: integer);
+begin
+
+end;
+
+constructor TFPCompactImgRGB16Bit.Create(AWidth, AHeight: integer);
+begin
+  FDesc:=GetFPCompactImgDesc(false,16,false);
+  inherited Create(AWidth, AHeight);
+end;
+
+destructor TFPCompactImgRGB16Bit.Destroy;
+begin
+  ReAllocMem(FData,0);
+  inherited Destroy;
+end;
+
+procedure TFPCompactImgRGB16Bit.SetSize(AWidth, AHeight: integer);
+begin
+  if (AWidth=Width) and (AHeight=Height) then exit;
+  ReAllocMem(FData,SizeOf(TFPCompactImgRGB16BitValue)*AWidth*AHeight);
+  inherited SetSize(AWidth,AHeight);
+end;
+
+{ TFPCompactImgRGBA16Bit }
+
+function TFPCompactImgRGBA16Bit.GetInternalColor(x, y: integer): TFPColor;
+begin
+  Result:=FData[x+y*Width];
+end;
+
+function TFPCompactImgRGBA16Bit.GetInternalPixel(x, y: integer): integer;
+begin
+  Result:=0;
+end;
+
+procedure TFPCompactImgRGBA16Bit.SetInternalColor(x, y: integer;
+  const Value: TFPColor);
+begin
+  FData[x+y*Width]:=Value;
+end;
+
+procedure TFPCompactImgRGBA16Bit.SetInternalPixel(x, y: integer; Value: integer);
+begin
+
+end;
+
+constructor TFPCompactImgRGBA16Bit.Create(AWidth, AHeight: integer);
+begin
+  FDesc:=GetFPCompactImgDesc(false,16,true);
+  inherited Create(AWidth, AHeight);
+end;
+
+destructor TFPCompactImgRGBA16Bit.Destroy;
+begin
+  ReAllocMem(FData,0);
+  inherited Destroy;
+end;
+
+procedure TFPCompactImgRGBA16Bit.SetSize(AWidth, AHeight: integer);
+begin
+  if (AWidth=Width) and (AHeight=Height) then exit;
+  ReAllocMem(FData,SizeOf(TFPColor)*AWidth*AHeight);
+  inherited SetSize(AWidth,AHeight);
+end;
+
+

+ 197 - 0
packages/fcl-image/src/fpimage.pp

@@ -343,6 +343,202 @@ function CreateWebSafePalette : TFPPalette;
 function CreateGrayScalePalette : TFPPalette;
 function CreateVGAPalette : TFPPalette;
 
+Type
+  TFPCompactImgDesc = record
+    Gray: boolean; // true = red=green=blue, false: a RGB image
+    Depth: word; // 8 or 16 bit
+    HasAlpha: boolean; // has alpha channel
+  end;
+
+  { TFPCompactImgBase }
+
+  TFPCompactImgBase = class(TFPCustomImage)
+  private
+    FDesc: TFPCompactImgDesc;
+  public
+    property Desc: TFPCompactImgDesc read FDesc;
+  end;
+  TFPCompactImgBaseClass = class of TFPCompactImgBase;
+
+  { TFPCompactImgGray16Bit }
+
+  TFPCompactImgGray16Bit = class(TFPCompactImgBase)
+  protected
+    FData: PWord;
+    function GetInternalColor(x, y: integer): TFPColor; override;
+    function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
+    procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
+    procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
+  public
+    constructor Create(AWidth, AHeight: integer); override;
+    destructor Destroy; override;
+    procedure SetSize(AWidth, AHeight: integer); override;
+  end;
+
+  TFPCompactImgGrayAlpha16BitValue = packed record
+    g,a: word;
+  end;
+  PFPCompactImgGrayAlpha16BitValue = ^TFPCompactImgGrayAlpha16BitValue;
+
+  { TFPCompactImgGrayAlpha16Bit }
+
+  TFPCompactImgGrayAlpha16Bit = class(TFPCompactImgBase)
+  protected
+    FData: PFPCompactImgGrayAlpha16BitValue;
+    function GetInternalColor(x, y: integer): TFPColor; override;
+    function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
+    procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
+    procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
+  public
+    constructor Create(AWidth, AHeight: integer); override;
+    destructor Destroy; override;
+    procedure SetSize(AWidth, AHeight: integer); override;
+  end;
+
+  { TFPCompactImgGray8Bit }
+
+  TFPCompactImgGray8Bit = class(TFPCompactImgBase)
+  protected
+    FData: PByte;
+    function GetInternalColor(x, y: integer): TFPColor; override;
+    function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
+    procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
+    procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
+  public
+    constructor Create(AWidth, AHeight: integer); override;
+    destructor Destroy; override;
+    procedure SetSize(AWidth, AHeight: integer); override;
+  end;
+
+  TFPCompactImgGrayAlpha8BitValue = packed record
+    g,a: byte;
+  end;
+  PFPCompactImgGrayAlpha8BitValue = ^TFPCompactImgGrayAlpha8BitValue;
+
+  { TFPCompactImgGrayAlpha8Bit }
+
+  TFPCompactImgGrayAlpha8Bit = class(TFPCompactImgBase)
+  protected
+    FData: PFPCompactImgGrayAlpha8BitValue;
+    function GetInternalColor(x, y: integer): TFPColor; override;
+    function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
+    procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
+    procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
+  public
+    constructor Create(AWidth, AHeight: integer); override;
+    destructor Destroy; override;
+    procedure SetSize(AWidth, AHeight: integer); override;
+  end;
+
+  TFPCompactImgRGBA8BitValue = packed record
+    r,g,b,a: byte;
+  end;
+  PFPCompactImgRGBA8BitValue = ^TFPCompactImgRGBA8BitValue;
+
+  { TFPCompactImgRGBA8Bit }
+
+  TFPCompactImgRGBA8Bit = class(TFPCompactImgBase)
+  protected
+    FData: PFPCompactImgRGBA8BitValue;
+    function GetInternalColor(x, y: integer): TFPColor; override;
+    function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
+    procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
+    procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
+  public
+    constructor Create(AWidth, AHeight: integer); override;
+    destructor Destroy; override;
+    procedure SetSize(AWidth, AHeight: integer); override;
+  end;
+
+  TFPCompactImgRGB8BitValue = packed record
+    r,g,b: byte;
+  end;
+  PFPCompactImgRGB8BitValue = ^TFPCompactImgRGB8BitValue;
+
+  { TFPCompactImgRGB8Bit }
+
+  TFPCompactImgRGB8Bit = class(TFPCompactImgBase)
+  protected
+    FData: PFPCompactImgRGB8BitValue;
+    function GetInternalColor(x, y: integer): TFPColor; override;
+    function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
+    procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
+    procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
+  public
+    constructor Create(AWidth, AHeight: integer); override;
+    destructor Destroy; override;
+    procedure SetSize(AWidth, AHeight: integer); override;
+  end;
+
+  TFPCompactImgRGB16BitValue = packed record
+    r,g,b: word;
+  end;
+  PFPCompactImgRGB16BitValue = ^TFPCompactImgRGB16BitValue;
+
+  { TFPCompactImgRGB16Bit }
+
+  TFPCompactImgRGB16Bit = class(TFPCompactImgBase)
+  protected
+    FData: PFPCompactImgRGB16BitValue;
+    function GetInternalColor(x, y: integer): TFPColor; override;
+    function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
+    procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
+    procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
+  public
+    constructor Create(AWidth, AHeight: integer); override;
+    destructor Destroy; override;
+    procedure SetSize(AWidth, AHeight: integer); override;
+  end;
+
+  { TFPCompactImgRGBA16Bit }
+
+  TFPCompactImgRGBA16Bit = class(TFPCompactImgBase)
+  protected
+    FData: PFPColor;
+    function GetInternalColor(x, y: integer): TFPColor; override;
+    function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
+    procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
+    procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
+  public
+    constructor Create(AWidth, AHeight: integer); override;
+    destructor Destroy; override;
+    procedure SetSize(AWidth, AHeight: integer); override;
+  end;
+
+{ Create a descriptor to select a CompactImg class }
+function GetFPCompactImgDesc(Gray: boolean; Depth: word; HasAlpha: boolean): TFPCompactImgDesc;
+
+{ Returns a CompactImg class that fits the descriptor }
+function GetFPCompactImgClass(const Desc: TFPCompactImgDesc): TFPCompactImgBaseClass;
+
+{ Create a CompactImg with the descriptor }
+function CreateFPCompactImg(const Desc: TFPCompactImgDesc; Width, Height: integer): TFPCustomImage;
+
+{ Create a CompactImg with the same features as Img.
+If Img is a TFPCompactImgBaseClass it will create that.
+Otherwise it returns a CompactImg that fits the Img using GetMinimumPTDesc. }
+function CreateCompatibleFPCompactImg(Img: TFPCustomImage; Width, Height: integer
+): TFPCustomImage;
+
+{ As CreateCompatibleFPCompactImg, but the image has always an alpha channel. }
+function CreateCompatibleFPCompactImgWithAlpha(Img: TFPCustomImage;
+Width, Height: integer): TFPCustomImage;
+
+{ Returns the smallest descriptor that allows to store the Img.
+It returns HasAlpha=false if all pixel are opaque.
+It returns Gray=true if all red=green=blue.
+It returns Depth=8 if all lo byte equals the hi byte or all lo bytes are 0.
+To ignore rounding errors you can pass a FuzzyDepth. For example a FuzzyDepth
+of 3 ignores the lower 3 bits when comparing.  }
+function GetMinimumPTDesc(Img: TFPCustomImage; FuzzyDepth: word = 4): TFPCompactImgDesc;
+
+{ Create a smaller CompactImg with the same information as Img.
+Pass FreeImg=true to call Img.Free }
+function GetMinimumFPCompactImg(Img: TFPCustomImage; FreeImg: boolean;
+FuzzyDepth: word = 4): TFPCustomImage;
+
+
+
 implementation
 
 procedure FPImgError (Fmt:TErrorTextIndices; data : array of const);
@@ -359,6 +555,7 @@ end;
 {$i FPHandler.inc}
 {$i FPPalette.inc}
 {$i FPColCnv.inc}
+{$i fpcompactimg.inc}
 
 function FPColor (r,g,b:word) : TFPColor;
 begin

+ 701 - 0
packages/fcl-image/src/fpimggauss.pp

@@ -0,0 +1,701 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by the Free Pascal development team
+
+    fpImage Gaussian blur routines by Mattias Gaertner
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************
+
+}
+
+unit FPImgGauss;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Math, Classes, FPimage;
+
+{ Fast Gaussian blur to Area (excluding Area.Right and Area.Bottom)
+  Pixels outside the image are treated as having the same color as the edge.
+  This is a binominal approximation of fourth degree, so it is pretty near the
+  real gaussian blur in most cases but much faster for big radius.
+  Runtime: O((Area.Width+Radius) * (Area.Height+Radius))  }
+procedure GaussianBlurBinominal4(AImg: TFPCustomImage; Radius: integer;
+  SrcArea: TRect);
+procedure GaussianBlurBinominal4(SrcImg, DestImg: TFPCustomImage; Radius: integer;
+  SrcArea: TRect; DestXY: TPoint);
+
+{ Gaussian blur to Area (excluding Area.Right and Area.Bottom)
+  Pixels outside the image are treated as having the same color as the edge.
+  Runtime: O(Area.Width * Area.Height * Radius)  }
+procedure GaussianBlur(Img: TFPCustomImage; Radius: integer; Area: TRect);
+
+{ MatrixBlur1D
+  The Matrix1D has a width of Radius*2+1.
+  The sum of all entries in the Matrix1D must be <= 65536.
+  Create Matrix1D with ComputeGaussianBlurMatrix1D.
+  Each pixel x,y in Area is replaced by a pixel computed from all pixels in
+  x-Radius..x+Radius, y-Radius..y+Radius
+  The new value is the sum of all pixels multiplied by Matrix1D, once
+  horizontally and once vertically.
+
+  Pixels outside the image are treated as having the same color as the edge.
+
+  Runtime is O(Area width * Area height * Radius) }
+procedure MatrixBlur1D(Img: TFPCustomImage; Radius: integer; Area: TRect; Matrix1D: PWord);
+
+{ MatrixBlur2D
+  The Matrix2D is quadratic and has a width of Radius*2+1.
+  The sum of all entries in the Matrix2D must be <= 65536.
+  Create Matrix2D with ComputeGaussianBlurMatrix2D.
+  Each pixel x,y in Area (Left..Right-1,Top..Bottom-1) is replaced by a pixel
+  computed from all pixels in x-Radius..x+Radius, y-Radius..y+Radius.
+  The new value is the sum of all pixels multiplied by Matrix2D.
+
+  Pixels outside the image are treated as having the same color as the edge.
+
+  Runtime is O(Area width * Area height * Radius * Radius) }
+procedure MatrixBlur2D(Img: TFPCustomImage; Radius: integer; Area: TRect; Matrix2D: PWord);
+
+{ ComputeGaussianBlurMatrix1D creates a one dimensional matrix of size
+  Width = Radius*2+1
+
+  Deviation := Radius / 3
+  G(x) := (1 / SQRT( 2 * pi * Deviation^2)) * e^( - (x^2) / (2 * Deviation^2) )
+
+  Each word is a factor [0,1) multiplied by 65536.
+  The total sum of the matrix is 65536. }
+function ComputeGaussianBlurMatrix1D(Radius: integer): PWord;
+
+{ ComputeGaussianBlurMatrix2D creates a two dimensional matrix of quadratic size
+  Width = Radius*2+1
+
+  Deviation := Radius / 3
+  G(x,y) := (1 / (2 * pi * Deviation^2)) * e^( - (x^2 + y^2) / (2 * Deviation^2) )
+
+  Each word is a factor [0,1) multiplied by 65536.
+  The total sum of the matrix is 65536. }
+function ComputeGaussianBlurMatrix2D(Radius: integer): PWord;
+
+implementation
+
+type
+
+  { TIntRingBuffer }
+
+  TIntRingBuffer = object
+  private
+    FSize: integer;
+    procedure SetSize(AValue: integer);
+  public
+    RingBuffer: PFPColor;
+    procedure Put(Index: integer; const Col: TFPColor);
+    procedure Get(Index: integer; out Col: TFPColor);
+    property Size: integer read FSize write SetSize;
+    procedure Init(len: integer);
+    procedure Clear;
+  end;
+
+{ TIntRingBuffer }
+
+procedure TIntRingBuffer.SetSize(AValue: integer);
+begin
+  if FSize=AValue then Exit;
+  FSize:=AValue;
+  ReAllocMem(RingBuffer,AValue*SizeOf(TFPColor));
+end;
+
+procedure TIntRingBuffer.Put(Index: integer; const Col: TFPColor);
+begin
+  Index:=Index mod FSize;
+  if Index<0 then inc(Index,FSize);
+  RingBuffer[Index]:=Col;
+end;
+
+procedure TIntRingBuffer.Get(Index: integer; out Col: TFPColor);
+begin
+  Index:=Index mod FSize;
+  if Index<0 then inc(Index,FSize);
+  Col:=RingBuffer[Index];
+end;
+
+procedure TIntRingBuffer.Init(len: integer);
+begin
+  FSize:=0;
+  RingBuffer:=nil;
+  Size:=len;
+end;
+
+procedure TIntRingBuffer.Clear;
+begin
+  Size:=0;
+end;
+
+procedure GaussianBlurBinominal4(AImg: TFPCustomImage; Radius: integer;
+  SrcArea: TRect);
+begin
+  GaussianBlurBinominal4(AImg,AImg,Radius,SrcArea,SrcArea.TopLeft);
+end;
+
+procedure GaussianBlurBinominal4(SrcImg, DestImg: TFPCustomImage;
+  Radius: integer; SrcArea: TRect; DestXY: TPoint);
+type
+  TIntegerColor = record
+    red, green, blue, alpha: integer;
+  end;
+const
+  clearIntegerColor: TIntegerColor = (red:0;green:0;blue:0;alpha:0);
+var
+  x,y,i: LongInt;
+  Pixel: TFPColor;
+  difference: TIntegerColor;
+  derivative1: TIntegerColor;
+  derivative2: TIntegerColor;
+  sum: TIntegerColor;
+  Weight: Single;
+  col: TFPColor;
+  buffer: TIntRingBuffer;
+  Col1, Col2, Col3, Col4: TFPColor;
+begin
+  // clip
+  if SrcArea.Left<0 then begin
+    dec(DestXY.X,SrcArea.Left);
+    SrcArea.Left:=0;
+  end;
+  if SrcArea.Top<0 then begin
+    dec(DestXY.Y,SrcArea.Top);
+    SrcArea.Top:=0;
+  end;
+  SrcArea.Right:=Min(SrcImg.Width,SrcArea.Right);
+  SrcArea.Top:=Min(SrcImg.Height,SrcArea.Top);
+  SrcArea.Right:=Min(SrcArea.Right,DestImg.Width-DestXY.X+SrcArea.Left);
+  SrcArea.Bottom:=Min(SrcArea.Bottom,DestImg.Height-DestXY.Y+SrcArea.Top);
+  if SrcArea.Left>=SrcArea.Right then exit;
+  if SrcArea.Top>=SrcArea.Bottom then exit;
+
+  // blur  -- RingBuffer of Size 147 is needed. range=(0,(int)(N_CELLS/4/1.73))
+  //                     N_CELLS=1024 don't ask! see paper: gauss.pdf, 3.sourcecdoe
+  //                     Or 4*Radius+1, sounds better. see Comment underneath
+  //Radius:=round(sqrt(3*Radius*Radius));
+  buffer.Init(4*Radius);
+  Weight := 1.0/(single(Radius*Radius*Radius*Radius));
+  // vertical blur
+  for x:=SrcArea.Left to SrcArea.Right-1 do begin
+    // set up init values for the first blur
+    difference:=clearIntegerColor;
+    derivative1:=clearIntegerColor;
+    derivative2:=clearIntegerColor;
+    sum:=clearIntegerColor;
+    for y:=SrcArea.Top-4*Radius to SrcArea.Bottom-1 do begin
+      if y >= SrcArea.Top then begin //{+1,-4,+6,-4,+1}
+        buffer.Get(y-2*Radius,Col1);
+        buffer.Get(y-Radius,Col2);
+        buffer.Get(y,Col3);
+        buffer.Get(y+Radius,Col4);
+        difference.alpha :=difference.alpha+Col1.alpha-4*(Col2.alpha+Col4.alpha)+6*Col3.alpha;
+        difference.red   :=difference.red  +Col1.red  -4*(Col2.red  +Col4.red)  +6*Col3.red;
+        difference.green :=difference.green+Col1.green-4*(Col2.green+Col4.green)+6*Col3.green;
+        difference.blue  :=difference.blue +Col1.blue -4*(Col2.blue +Col4.blue) +6*Col3.blue;
+        col:=SrcImg.Colors[x,y];
+        col.alpha:=min($FFFF,max(0,round(sum.alpha*Weight)));
+        col.red  :=min($FFFF,max(0,round(sum.red  *Weight)));
+        col.green:=min($FFFF,max(0,round(sum.green*Weight)));
+        col.blue :=min($FFFF,max(0,round(sum.blue *Weight)));
+        DestImg.Colors[x,y]:=col; // set blurred pixel
+      end else begin
+        if (y+3*Radius) >= SrcArea.Top then begin
+          // -4*buffer(y+Radius)
+          buffer.Get(y+Radius,Col4);
+          difference.alpha:=difference.alpha-4*Col4.alpha;
+          difference.red  :=difference.red  -4*Col4.red;
+          difference.green:=difference.green-4*Col4.green;
+          difference.blue :=difference.blue -4*Col4.blue;
+        end;
+        if (y+2*Radius) >= SrcArea.Top then begin
+          // +6*buffer(y)
+          buffer.Get(y,Col3);
+          difference.alpha:=difference.alpha+6*Col4.alpha;
+          difference.red  :=difference.red  +6*Col4.red;
+          difference.green:=difference.green+6*Col4.green;
+          difference.blue :=difference.blue +6*Col4.blue;
+        end;
+        if (y+  Radius) >= SrcArea.Top then begin
+          // -4*buffer(y-Radius)
+          buffer.Get(y-Radius,Col2);
+          difference.alpha:=difference.alpha-4*Col2.alpha;
+          difference.red  :=difference.red  -4*Col2.red;
+          difference.green:=difference.green-4*Col2.green;
+          difference.blue :=difference.blue -4*Col2.blue;
+        end;
+      end;
+      i:=Min(DestImg.Height-1,Max(0,y+2*Radius-1));
+      // accumulate pixel blur
+      pixel := SrcImg.Colors[x,i];
+      difference.alpha := difference.alpha+pixel.alpha;
+      difference.red   := difference.red  +pixel.red;
+      difference.green := difference.green+pixel.green;
+      difference.blue  := difference.blue +pixel.blue;
+      derivative2.alpha := derivative2.alpha+difference.alpha;
+      derivative2.red   := derivative2.red  +difference.red;
+      derivative2.green := derivative2.green+difference.green;
+      derivative2.blue  := derivative2.blue +difference.blue;
+      derivative1.alpha := derivative1.alpha+derivative2.alpha;
+      derivative1.red   := derivative1.red  +derivative2.red;
+      derivative1.green := derivative1.green+derivative2.green;
+      derivative1.blue  := derivative1.blue +derivative2.blue;
+      sum.alpha := sum.alpha+derivative1.alpha;
+      sum.red   := sum.red  +derivative1.red;
+      sum.green := sum.green+derivative1.green;
+      sum.blue  := sum.blue +derivative1.blue;
+      buffer.Put(y+2*Radius,pixel);  // buffer pixel, min buffer size: 4*Radius
+    end;
+  end;
+
+  //horizontal blur
+  for y:=SrcArea.Top to SrcArea.Bottom-1 do begin
+    // set up init values for the first blur
+    difference:=clearIntegerColor;
+    derivative1:=clearIntegerColor;
+    derivative2:=clearIntegerColor;
+    sum:=clearIntegerColor;
+    for x:=SrcArea.Left-4*Radius to SrcArea.Right-1 do begin
+      if x >= SrcArea.Left then begin //{+1,-4,+6,-4,+1}
+        buffer.Get(x-2*Radius,Col1);
+        buffer.Get(x-Radius,Col2);
+        buffer.Get(x,Col3);
+        buffer.Get(x+Radius,Col4);
+        difference.alpha :=difference.alpha+Col1.alpha-4*(Col2.alpha+Col4.alpha)+6*Col3.alpha;
+        difference.red   :=difference.red  +Col1.red  -4*(Col2.red  +Col4.red)  +6*Col3.red;
+        difference.green :=difference.green+Col1.green-4*(Col2.green+Col4.green)+6*Col3.green;
+        difference.blue  :=difference.blue +Col1.blue -4*(Col2.blue +Col4.blue) +6*Col3.blue;
+        col:=DestImg.Colors[x,y];
+        col.alpha:=min($FFFF,max(0,round(sum.alpha*Weight)));
+        col.red  :=min($FFFF,max(0,round(sum.red  *Weight)));
+        col.green:=min($FFFF,max(0,round(sum.green*Weight)));
+        col.blue :=min($FFFF,max(0,round(sum.blue *Weight)));
+        DestImg.Colors[x,y]:=col; // set blurred pixel
+      end else begin
+        if (x+3*Radius) >= SrcArea.Left then begin
+          // -4*buffer(x+Radius)
+          buffer.Get(x+Radius,Col4);
+          difference.alpha:=difference.alpha-4*Col4.alpha;
+          difference.red  :=difference.red  -4*Col4.red;
+          difference.green:=difference.green-4*Col4.green;
+          difference.blue :=difference.blue -4*Col4.blue;
+        end;
+        if (x+2*Radius) >= SrcArea.Left then begin
+          // +6*buffer(x)
+          buffer.Get(x,Col3);
+          difference.alpha:=difference.alpha+6*Col3.alpha;
+          difference.red  :=difference.red  +6*Col3.red;
+          difference.green:=difference.green+6*Col3.green;
+          difference.blue :=difference.blue +6*Col3.blue;
+        end;
+        if (x+  Radius) >= SrcArea.Left then begin
+          // -4*buffer(x-Radius)
+          buffer.Get(x-Radius,Col2);
+          difference.alpha:=difference.alpha-4*Col2.alpha;
+          difference.red  :=difference.red  -4*Col2.red;
+          difference.green:=difference.green-4*Col2.green;
+          difference.blue :=difference.blue -4*Col2.blue;
+        end;
+      end;
+      i:=Min(DestImg.Width-1,Max(0,x+2*Radius-1));
+      // accumulate pixel blur
+      pixel := DestImg.Colors[i,y];
+      difference.alpha := difference.alpha+pixel.alpha;
+      difference.red   := difference.red  +pixel.red;
+      difference.green := difference.green+pixel.green;
+      difference.blue  := difference.blue +pixel.blue;
+      derivative2.alpha := derivative2.alpha+difference.alpha;
+      derivative2.red   := derivative2.red  +difference.red;
+      derivative2.green := derivative2.green+difference.green;
+      derivative2.blue  := derivative2.blue +difference.blue;
+      derivative1.alpha := derivative1.alpha+derivative2.alpha;
+      derivative1.red   := derivative1.red  +derivative2.red;
+      derivative1.green := derivative1.green+derivative2.green;
+      derivative1.blue  := derivative1.blue +derivative2.blue;
+      sum.alpha := sum.alpha+derivative1.alpha;
+      sum.red   := sum.red  +derivative1.red;
+      sum.green := sum.green+derivative1.green;
+      sum.blue  := sum.blue +derivative1.blue;
+
+      buffer.Put(x+2*Radius,pixel);  // buffer pixel, min buffer size: 4*Radius
+    end;
+  end;
+  buffer.Clear;
+end;
+
+procedure GaussianBlur(Img: TFPCustomImage; Radius: integer; Area: TRect);
+var
+  Matrix: PWord;
+begin
+  // check input
+  if (Radius<1) then exit;
+  Area.Left:=Max(0,Area.Left);
+  Area.Top:=Max(0,Area.Top);
+  Area.Right:=Min(Area.Right,Img.Width);
+  Area.Bottom:=Min(Area.Bottom,Img.Height);
+  if (Area.Left>=Area.Right) or (Area.Top>=Area.Bottom) then exit;
+
+  // compute gaussian matrix
+  Matrix:=ComputeGaussianBlurMatrix1D(Radius);
+  try
+    MatrixBlur1D(Img,Radius,Area,Matrix);
+  finally
+    FreeMem(Matrix);
+  end;
+end;
+
+procedure MatrixBlur1D(Img: TFPCustomImage; Radius: integer; Area: TRect;
+  Matrix1D: PWord);
+{ Implementation:
+    It runs line by line from Area.Left to Area.Bottom-1.
+    It allocates some temporary memory to store the original pixel values
+    above the current line.
+}
+var
+  y: Integer;
+  x: Integer;
+  OrigWidth: Integer;
+  OrigHeight: LongInt;
+  OrigPixels: PFPColor;
+  VertSums: PFPColor;
+  NewRed, NewGreen, NewBlue, NewAlpha: cardinal;
+  yd: LongInt;
+  xd: LongInt;
+  xr: Integer;
+  yr: Integer;
+  Col: TFPColor;
+  NewCol: TFPColor;
+  Multiplier: Word;
+  StartX: Integer;
+  EndX: Integer;
+begin
+  // check input
+  if (Radius<1) then exit;
+  Area.Left:=Max(0,Area.Left);
+  Area.Top:=Max(0,Area.Top);
+  Area.Right:=Min(Area.Right,Img.Width);
+  Area.Bottom:=Min(Area.Bottom,Img.Height);
+  if (Area.Left>=Area.Right) or (Area.Top>=Area.Bottom) then exit;
+
+  //for x:=0 to MatrixWidth-1 do WriteLn('GaussianBlurNew ',x,' ',Matrix[x]);
+  OrigPixels:=nil;
+  VertSums:=nil;
+  try
+    // allocate space for original pixels
+    OrigWidth:=Area.Right-Area.Left;
+    OrigHeight:=Radius+1;
+    //writeln('GaussianBlur ',OrigWidth,'*',OrigHeight,'*',SizeOf(TFPColor));
+    GetMem(OrigPixels,OrigWidth*OrigHeight*SizeOf(TFPColor));
+    // get original pixels (the bottom line of OrigPixels will be Area.Top)
+    y:=Area.Top;
+    for yd:=-Radius to 0 do begin
+      yr:=Max(0,y+yd);
+      for x:=Area.Left to Area.Right-1 do begin
+        OrigPixels[x-Area.Left+(yd+Radius)*OrigWidth]:=Img.Colors[x,yr];
+      end;
+    end;
+
+    GetMem(VertSums,(OrigWidth+2*Radius)*SizeOf(TFPColor));
+
+    // compute new pixels
+    for y:=Area.Top to Area.Bottom-1 do begin
+      // move OrigPixels one line up
+      System.Move(OrigPixels[OrigWidth],OrigPixels[0],
+        OrigWidth*(OrigHeight-1)*SizeOf(TFPColor));
+      // and copy current line to OrigPixels
+      for x:=Area.Left to Area.Right-1 do begin
+        OrigPixels[x-Area.Left+Radius*OrigWidth]:=Img.Colors[x,y];
+      end;
+
+      // compute vertical sums
+      // (for each x compute the sum of y-Radius..y+Radius colors
+      //  multiplied with the gaussian matrix)
+      StartX:=Area.Left-Radius;
+      EndX:=Area.Right-1+Radius;
+      for x:=StartX to EndX do begin
+        // xr: x coordinate on img (coords out of bounds are mapped to the edges)
+        xr:=Min(Max(0,x),Img.Width-1);
+        // compute new color for this pixel
+        NewRed:=0;
+        NewGreen:=0;
+        NewBlue:=0;
+        NewAlpha:=0;
+        for yd:=-Radius to Radius do begin
+          // yr: y coordinate on img (coords out of bounds are mapped to the edges)
+          yr:=Min(Max(0,y+yd),Img.Height-1);
+          // get color
+          if (yd<=0) and (xr>=Area.Left) and (xr<Area.Right) then begin
+            // this pixel was replaced => use the OrigPixels
+            Col:=OrigPixels[xr-Area.Left+(yd+Radius)*OrigWidth];
+          end else begin
+            Col:=Img.Colors[xr,yr];
+          end;
+          // multiply with gaussian matrix
+          Multiplier:=Matrix1D[yd+Radius];
+          inc(NewRed,Col.red*Multiplier);
+          inc(NewGreen,Col.green*Multiplier);
+          inc(NewBlue,Col.blue*Multiplier);
+          inc(NewAlpha,Col.alpha*Multiplier);
+          //writeln('GaussianBlur x=',x,' y=',y,' xd=',xd,' yd=',yd,' xr=',xr,' yr=',yr,' Col=',dbgs(Col),' NewCol=r=',hexstr(NewRed,8),'g=',hexstr(NewGreen,8),'b=',hexstr(NewBlue,8),'a=',hexstr(NewAlpha,8));
+        end;
+        NewCol.red:=NewRed shr 16;
+        NewCol.green:=NewGreen shr 16;
+        NewCol.blue:=NewBlue shr 16;
+        NewCol.alpha:=NewAlpha shr 16;
+        VertSums[x-StartX]:=NewCol;
+      end;
+
+      // compute horizontal sums
+      // (for each x compute the sum of x-Radius..x+Radius vertical sums
+      //  multiplied with the gaussian matrix)
+      for x:=Area.Left to Area.Right-1 do begin
+        // compute new color for this pixel
+        NewRed:=0;
+        NewGreen:=0;
+        NewBlue:=0;
+        NewAlpha:=0;
+        for xd:=-Radius to Radius do begin
+          xr:=x+xd;
+          Col:=VertSums[xr-StartX];
+          // multiply with gaussian matrix
+          Multiplier:=Matrix1D[xd+Radius];
+          inc(NewRed,Col.red*Multiplier);
+          inc(NewGreen,Col.green*Multiplier);
+          inc(NewBlue,Col.blue*Multiplier);
+          inc(NewAlpha,Col.alpha*Multiplier);
+          //writeln('GaussianBlur x=',x,' y=',y,' xd=',xd,' yd=',yd,' xr=',xr,' yr=',yr,' Col=',dbgs(Col),' NewCol=r=',hexstr(NewRed,8),'g=',hexstr(NewGreen,8),'b=',hexstr(NewBlue,8),'a=',hexstr(NewAlpha,8));
+        end;
+        NewCol.red:=NewRed shr 16;
+        NewCol.green:=NewGreen shr 16;
+        NewCol.blue:=NewBlue shr 16;
+        NewCol.alpha:=NewAlpha shr 16;
+        // set new pixel
+        //writeln('GaussianBlur x=',x,' y=',y,' OldCol=',dbgs(img.Colors[x,y]),' NewCol=',dbgs(NewCol));
+        Img.Colors[x,y]:=NewCol;
+      end;
+    end;
+  finally
+    if OrigPixels<>nil then FreeMem(OrigPixels);
+    if VertSums<>nil then FreeMem(VertSums);
+  end;
+end;
+
+procedure MatrixBlur2D(Img: TFPCustomImage; Radius: integer; Area: TRect;
+  Matrix2D: PWord);
+{ Implementation:
+    It runs line by line from Area.Left to Area.Bottom-1.
+    It allocates some temporary memory to store the original pixel values
+    above the current line.
+}
+var
+  y: Integer;
+  x: Integer;
+  OrigWidth: Integer;
+  OrigHeight: LongInt;
+  OrigPixels: PFPColor;
+  NewRed, NewGreen, NewBlue, NewAlpha: cardinal;
+  yd: LongInt;
+  xd: LongInt;
+  xr: Integer;
+  yr: Integer;
+  Col: TFPColor;
+  NewCol: TFPColor;
+  Multiplier: Word;
+  MatrixWidth: Integer;
+begin
+  // check input
+  if (Radius<1) then exit;
+  Area.Left:=Max(0,Area.Left);
+  Area.Top:=Max(0,Area.Top);
+  Area.Right:=Min(Area.Right,Img.Width);
+  Area.Bottom:=Min(Area.Bottom,Img.Height);
+  if (Area.Left>=Area.Right) or (Area.Top>=Area.Bottom) then exit;
+
+  MatrixWidth:=Radius*2+1;
+  //WriteM('matrix ',Matrix2D,MatrixWidth);
+  OrigPixels:=nil;
+  try
+    // allocate space for original pixels
+    OrigWidth:=Area.Right-Area.Left;
+    OrigHeight:=Radius+1;
+    //DebugLn(['GaussianBlur ',OrigWidth,'*',OrigHeight,'*',SizeOf(TFPColor)]);
+    GetMem(OrigPixels,OrigWidth*OrigHeight*SizeOf(TFPColor));
+    // get original pixels (the bottom line of OrigPixels will be Area.Top)
+    y:=Area.Top;
+    for yd:=-Radius to 0 do begin
+      yr:=Max(0,y+yd);
+      for x:=Area.Left to Area.Right-1 do begin
+        OrigPixels[x-Area.Left+(yd+Radius)*OrigWidth]:=Img.Colors[x,yr];
+      end;
+    end;
+
+    // compute new pixels
+    for y:=Area.Top to Area.Bottom-1 do begin
+      // move OrigPixels one line up
+      System.Move(OrigPixels[OrigWidth],OrigPixels[0],
+        OrigWidth*(OrigHeight-1)*SizeOf(TFPColor));
+      // and copy current line to OrigPixels
+      for x:=Area.Left to Area.Right-1 do begin
+        OrigPixels[x-Area.Left+Radius*OrigWidth]:=Img.Colors[x,y];
+      end;
+      // compute line
+      for x:=Area.Left to Area.Right-1 do begin
+        // compute new color for this pixel
+        NewRed:=0;
+        NewGreen:=0;
+        NewBlue:=0;
+        NewAlpha:=0;
+        for yd:=-Radius to Radius do begin
+          // yr: y coordinate on img (coords out of bounds are mapped to the edges)
+          yr:=Min(Max(0,y+yd),Img.Height-1);
+          for xd:=-Radius to Radius do begin
+            // xr: x coordinate on img (coords out of bounds are mapped to the edges)
+            xr:=Min(Max(0,x+xd),Img.Width-1);
+            // get color
+            if (yd<=0) and (xr>=Area.Left) and (xr<Area.Right) then begin
+              // this pixel was replaced => use the OrigPixels
+              Col:=OrigPixels[xr-Area.Left+(yd+Radius)*OrigWidth];
+            end else begin
+              Col:=Img.Colors[xr,yr];
+            end;
+            // multiply with gauss Matrix2D
+            Multiplier:=Matrix2D[xd+Radius+(yd+Radius)*MatrixWidth];
+            inc(NewRed,Col.red*Multiplier);
+            inc(NewGreen,Col.green*Multiplier);
+            inc(NewBlue,Col.blue*Multiplier);
+            inc(NewAlpha,Col.alpha*Multiplier);
+            //DebugLn(['GaussianBlur x=',x,' y=',y,' xd=',xd,' yd=',yd,' xr=',xr,' yr=',yr,' Col=',dbgs(Col),' NewCol=r=',hexstr(NewRed,8),'g=',hexstr(NewGreen,8),'b=',hexstr(NewBlue,8),'a=',hexstr(NewAlpha,8)]);
+          end;
+        end;
+        NewCol.red:=NewRed shr 16;
+        NewCol.green:=NewGreen shr 16;
+        NewCol.blue:=NewBlue shr 16;
+        NewCol.alpha:=NewAlpha shr 16;
+        // set new pixel
+        //DebugLn(['GaussianBlur x=',x,' y=',y,' OldCol=',dbgs(img.Colors[x,y]),' NewCol=',dbgs(NewCol)]);
+        Img.Colors[x,y]:=NewCol;
+      end;
+    end;
+  finally
+    if OrigPixels<>nil then FreeMem(OrigPixels);
+  end;
+end;
+
+function ComputeGaussianBlurMatrix1D(Radius: integer): PWord;
+// returns a 1dim matrix of Words for the gaussian blur.
+// Each word is a factor [0,1) multiplied by 65536.
+// The total sum of the matrix is 65536.
+const
+  StandardDeviationToRadius = 3; // Pixels more far away as 3*Deviation are too small
+var
+  Width: Integer;
+  Size: Integer;
+  Matrix: PWord;
+  Deviation: Single;
+  m,p: Single;
+  x: Integer;
+  Value: Integer;
+  MatrixSum: Integer;
+  g: Single;
+begin
+  Width:=Radius*2+1;
+  Size:=SizeOf(Word)*Width*Width;
+  Matrix:=nil;
+  GetMem(Matrix,Size);
+  Result:=Matrix;
+  FillByte(Matrix^,Size,0);
+  // Deviation := Radius / 3
+  // G(x) := (1 / SQRT( 2 * pi * Deviation^2)) * e^( - (x^2) / (2 * Deviation^2) )
+  //                     m                     * e^(    x^2  *  p )
+  // m := 1 / SQRT( 2 * pi * Deviation^2)
+  // p := -1 / (2 * Deviation^2)
+  Deviation:=single(Radius)/StandardDeviationToRadius;
+  m:=1/Sqrt(2*pi*Deviation*Deviation);
+  p:=-1/(2*Deviation*Deviation);
+  for x:=0 to Radius do begin
+    g:=m*exp(single(x*x)*p);
+    Value:=floor(g*65536);
+    Matrix[Radius+x]:=Value;
+    Matrix[Radius-x]:=Value;
+  end;
+  // fix sum to 65536
+  MatrixSum:=0;
+  for x:=0 to Width-1 do
+    inc(MatrixSum,Matrix[x]);
+  Matrix[Radius]:=Min(High(Word),65536-MatrixSum+Matrix[Radius]);
+end;
+
+function ComputeGaussianBlurMatrix2D(Radius: integer): PWord;
+// returns a 2dim matrix of Words for the gaussian blur.
+// Each word is a factor [0,1) multiplied by 65536.
+// The total sum of the matrix is 65536.
+const
+  StandardDeviationToRadius = 3; // Pixels more far away as 3*Deviation are too small
+var
+  Matrix: PWord;
+  Size: Integer;
+  Deviation: single;
+  m,p: single;
+  g: single;
+  y: Integer;
+  x: Integer;
+  yd: Integer;
+  xd: Integer;
+  MatrixSum: Integer;
+  Value: Word;
+  Width: Integer;
+begin
+  Width:=Radius*2+1;
+  Size:=SizeOf(Word)*Width*Width;
+  Matrix:=nil;
+  GetMem(Matrix,Size);
+  Result:=Matrix;
+  FillByte(Matrix^,Size,0);
+  // Deviation = Radius / StandardDeviationToRadius
+  // G(x,y) := (1 / (2 * pi * Deviation^2)) * e^( - (x^2 + y^2) / (2 * Deviation^2) )
+  //         =              m               * e^(   (x^2 + y^2) *   p       )
+  // m := 1 / (2 * pi * Deviation^2)
+  // p := -1 / (2 * Deviation^2)
+  Deviation:=single(Radius)/StandardDeviationToRadius;
+  m:=1/(2*pi*Deviation*Deviation);
+  p:=-1/(2*Deviation*Deviation);
+  for y:=0 to Radius do begin
+    yd:=Radius-y;
+    yd:=yd*yd;
+    for x:=y to Radius do begin
+      xd:=Radius-x;
+      xd:=xd*xd;
+      g:=m*exp((single(xd)+single(yd))*p);
+      Value:=floor(g*65536);
+      Matrix[x+y*Width]:=Value;
+      // mirror diagonally
+      Matrix[y+x*Width]:=Value;
+    end;
+    // mirror horizontally
+    for x:=Radius+1 to Width-1 do
+      Matrix[x+y*Width]:=Matrix[(Width-x-1)+y*Width];
+    // mirror vertically
+    System.Move(Matrix[y*Width],Matrix[(Width-y-1)*Width],SizeOf(Word)*Width);
+  end;
+  // fix sum to 65536
+  MatrixSum:=0;
+  for y:=0 to Width-1 do
+    for x:=0 to Width-1 do
+      inc(MatrixSum,Matrix[x+y*Width]);
+  Matrix[Radius+Radius*Width]:=Min(High(Word),65536-MatrixSum+Matrix[Radius+Radius*Width]);
+end;
+
+end.
+

+ 2 - 2
packages/fcl-image/src/fpinterpolation.inc

@@ -179,7 +179,7 @@ begin
         begin
           sx:=PInteger(xEntry)^;
           inc(xEntry,SizeOf(integer));
-          NewCol:=colBlack;
+          NewCol:= colTransparent;
           for cx:=0 to xSupport-1 do
           begin
             f:=PSingle(xEntry)^;
@@ -198,7 +198,7 @@ begin
       for dx:=0 to w-1 do
       begin
         CurEntry:=yEntry+SizeOf(integer);
-        NewCol:=colBlack;
+        NewCol:=colTransparent;
         for sy:=0 to ySupport-1 do
         begin
           f:=PSingle(CurEntry)^;

File diff suppressed because it is too large
+ 508 - 140
packages/fcl-image/src/fpreadtiff.pas


+ 223 - 52
packages/fcl-image/src/fptiffcmn.pas

@@ -1,6 +1,6 @@
 {
     This file is part of the Free Pascal run time library.
-    Copyright (c) 2008 by the Free Pascal development team
+    Copyright (c) 2012 by the Free Pascal development team
 
     Common stuff for Tiff image format.
 
@@ -28,6 +28,8 @@ type
   end;
 
 const
+  TiffHandlerName = 'Tagged Image File Format';
+
   TiffRational0: TTiffRational = (Numerator: 0; Denominator: 0);
   TiffRational72: TTiffRational = (Numerator: 72; Denominator: 1);
 
@@ -44,17 +46,66 @@ const
   TiffDocumentName = TiffExtraPrefix+'DocumentName';
   TiffDateTime = TiffExtraPrefix+'DateTime';
   TiffImageDescription = TiffExtraPrefix+'ImageDescription';
+  TiffHostComputer = TiffExtraPrefix+'HostComputer';
+  TiffMake_ScannerManufacturer = TiffExtraPrefix+'Make_ScannerManufacturer';
+  TiffModel_Scanner = TiffExtraPrefix+'Model_Scanner';
   TiffOrientation = TiffExtraPrefix+'Orientation';
   TiffResolutionUnit = TiffExtraPrefix+'ResolutionUnit';
+  TiffSoftware = TiffExtraPrefix+'Software';
   TiffXResolution = TiffExtraPrefix+'XResolution';
   TiffYResolution = TiffExtraPrefix+'YResolution';
+  TiffPageNumber = TiffExtraPrefix+'PageNumber'; // starting at 0
+  TiffPageCount = TiffExtraPrefix+'PageCount'; // if >0 the image is a page
+  TiffPageName = TiffExtraPrefix+'PageName';
+  TiffIsThumbnail = TiffExtraPrefix+'IsThumbnail';
+  TiffIsMask = TiffExtraPrefix+'IsMask';
+  TiffTileWidth = TiffExtraPrefix+'TileWidth';
+  TiffTileLength = TiffExtraPrefix+'TileLength';
+  TiffCompression = TiffExtraPrefix+'Compression'; // number
 
+  TiffCompressionNone = 1; { No Compression, but pack data into bytes as tightly as possible,
+       leaving no unused bits (except at the end of a row). The component
+       values are stored as an array of type BYTE. Each scan line (row)
+       is padded to the next BYTE boundary. }
+  TiffCompressionCCITTRLE = 2; { CCITT Group 3 1-Dimensional Modified Huffman run length encoding. }
+  TiffCompressionCCITTFAX3 = 3; { CCITT Group 3 fax encoding }
+  TiffCompressionCCITTFAX4 = 4; { CCITT Group 4 fax encoding }
+  TiffCompressionLZW = 5; { LZW }
+  TiffCompressionOldJPEG = 6; { JPEG old style}
+  TiffCompressionJPEG = 7; { JPEG new style }
+  TiffCompressionDeflateAdobe = 8; { Deflate Adobe style }
+  TiffCompressionJBIGBW = 9; { RFC2301 JBIG black/white }
+  TiffCompressionJBIGCol = 10; { RFC2301 JBIG color }
+  TiffCompressionNeXT = 32766; { Next }
+  TiffCompressionCCITTRLEW = 32771; { CCITTRLEW }
+  TiffCompressionPackBits = 32773; { PackBits Compression, a simple byte-oriented run length scheme.
+         See the PackBits section for details. Data Compression applies
+         only to raster image data. All other TIFF fields are unaffected. }
+  TiffCompressionThunderScan = 32809; { THUNDERSCAN }
+  TiffCompressionIT8CTPAD = 32895; { IT8CTPAD }
+  TiffCompressionIT8LW = 32896; { IT8LW }
+  TiffCompressionIT8MP = 32897; { IT8MP }
+  TiffCompressionIT8BL = 32898; { IT8BL }
+  TiffCompressionPixarFilm = 32908; { PIXARFILM }
+  TiffCompressionPixarLog = 32909; { PIXARLOG }
+  TiffCompressionDeflateZLib = 32946; { DeflatePKZip }
+  TiffCompressionDCS = 32947; { DCS }
+  TiffCompressionJBIG = 34661; { JBIG }
+  TiffCompressionSGILog = 34676; { SGILOG }
+  TiffCompressionSGILog24 = 34677; { SGILOG24 }
+  TiffCompressionJPEG2000 = 34712; { JP2000 }
 type
+  TTiffChunkType = (
+    tctStrip,
+    tctTile
+    );
 
-  { TTiffIDF }
+  { TTiffIFD - Image File Directory }
 
-  TTiffIDF = class
+  TTiffIFD = class
   public
+    IFDStart: DWord; // tiff position
+    IFDNext: DWord; // tiff position
     Artist: String;
     BitsPerSample: DWord; // tiff position of entry
     BitsPerSampleArray: array of Word;
@@ -78,6 +129,9 @@ type
     Make_ScannerManufacturer: string;
     Model_Scanner: string;
     Orientation: DWord;
+    PageNumber: word; // the page number starting at 0, the total number of pages is PageCount
+    PageCount: word; // see PageNumber
+    PageName: string;
     PhotoMetricInterpretation: DWord;
     PlanarConfiguration: DWord;
     ResolutionUnit: DWord;
@@ -86,11 +140,16 @@ type
     Software: string;
     StripByteCounts: DWord;// tiff position of entry
     StripOffsets: DWord; // tiff position of entry
-    Treshholding: DWord;
+    TileWidth: DWord;
+    TileLength: DWord; // = Height
+    TileOffsets: DWord; // tiff position of entry
+    TileByteCounts: DWord; // tiff position of entry
+    Tresholding: DWord;
     XResolution: TTiffRational;
     YResolution: TTiffRational;
     // image
     Img: TFPCustomImage;
+    FreeImg: boolean;
     RedBits: word;
     GreenBits: word;
     BlueBits: word;
@@ -98,7 +157,10 @@ type
     AlphaBits: word;
     BytesPerPixel: Word;
     procedure Clear;
-    procedure Assign(IDF: TTiffIDF);
+    procedure Assign(IFD: TTiffIFD);
+    procedure ReadFPImgExtras(Src: TFPCustomImage);
+    function ImageLength: DWord; inline;
+    destructor Destroy; override;
   end;
 
 function TiffRationalToStr(const r: TTiffRational): string;
@@ -106,6 +168,7 @@ function StrToTiffRationalDef(const s: string; const Def: TTiffRational): TTiffR
 procedure ClearTiffExtras(Img: TFPCustomImage);
 procedure CopyTiffExtras(SrcImg, DestImg: TFPCustomImage);
 procedure WriteTiffExtras(Msg: string; Img: TFPCustomImage);
+function TiffCompressionName(c: Word): string;
 
 implementation
 
@@ -149,22 +212,54 @@ procedure WriteTiffExtras(Msg: string; Img: TFPCustomImage);
 var
   i: Integer;
 begin
-  {$ifdef FPC_Debug_Image}
   writeln('WriteTiffExtras ',Msg);
-
-  for i:=Img.ExtraCount-1 downto 0 do
+  for i:=0 to Img.ExtraCount-1 do
     //if SysUtils.CompareText(copy(Img.ExtraKey[i],1,4),'Tiff')=0 then
       writeln('  ',i,' ',Img.ExtraKey[i],'=',Img.ExtraValue[i]);
-  {$endif}      
 end;
 
-{ TTiffIDF }
+function TiffCompressionName(c: Word): string;
+begin
+  case c of
+  1: Result:='no compression';
+  2: Result:='CCITT Group 3 1-Dimensional Modified Huffman run length encoding';
+  3: Result:='CCITT Group 3 fax encoding';
+  4: Result:='CCITT Group 4 fax encoding';
+  5: Result:='LZW';
+  6: Result:='JPEG old style';
+  7: Result:='JPEG';
+  8: Result:='Deflate Adobe style';
+  9: Result:='RFC2301 JBIG white/black';
+  10: Result:='RFC2301 JBIG color';
+  32766: Result:='NeXT';
+  32771: Result:='CCITTRLEW';
+  32773: Result:='PackBits';
+  32809: Result:='THUNDERSCAN';
+  32895: Result:='IT8CTPAD';
+  32896: Result:='IT8LW';
+  32897: Result:='IT8MP';
+  32898: Result:='IT8BL';
+  32908: Result:='PIXARFILM';
+  32909: Result:='PIXARLOG';
+  32946: Result:='Deflate ZLib';
+  32947: Result:='DCS';
+  34661: Result:='JBIG';
+  34676: Result:='SGILOG';
+  34677: Result:='SGILOG24';
+  34712: Result:='JP2000';
+  else Result:='unknown('+IntToStr(c)+')';
+  end;
+end;
+
+{ TTiffIFD }
 
-procedure TTiffIDF.Clear;
+procedure TTiffIFD.Clear;
 begin
+  IFDStart:=0;
+  IFDNext:=0;
   PhotoMetricInterpretation:=High(PhotoMetricInterpretation);
   PlanarConfiguration:=0;
-  Compression:=0;
+  Compression:=TiffCompressionNone;
   Predictor:=1;
   ImageHeight:=0;
   ImageWidth:=0;
@@ -192,7 +287,17 @@ begin
   CellLength:=0;
   FillOrder:=0;
   Orientation:=0;
-  Treshholding:=0;
+  PageNumber:=0;
+  PageCount:=0;
+  PageName:='';
+
+  // tiles
+  TileWidth:=0;
+  TileLength:=0;
+  TileOffsets:=0;
+  TileByteCounts:=0;
+
+  Tresholding:=0;
 
   RedBits:=0;
   GreenBits:=0;
@@ -200,48 +305,114 @@ begin
   GrayBits:=0;
   AlphaBits:=0;
   BytesPerPixel:=0;
+
+  if FreeImg then begin
+    FreeImg:=false;
+    FreeAndNil(Img);
+  end;
+end;
+
+procedure TTiffIFD.Assign(IFD: TTiffIFD);
+begin
+  IFDStart:=IFD.IFDStart;
+  IFDNext:=IFD.IFDNext;
+
+  PhotoMetricInterpretation:=IFD.PhotoMetricInterpretation;
+  PlanarConfiguration:=IFD.PlanarConfiguration;
+  Compression:=IFD.Compression;
+  Predictor:=IFD.Predictor;
+  ImageHeight:=IFD.ImageHeight;
+  ImageWidth:=IFD.ImageWidth;
+  ImageIsThumbNail:=IFD.ImageIsThumbNail;
+  ImageIsPage:=IFD.ImageIsPage;
+  ImageIsMask:=IFD.ImageIsMask;
+  BitsPerSample:=IFD.BitsPerSample;
+  BitsPerSampleArray:=IFD.BitsPerSampleArray;
+  ResolutionUnit:=IFD.ResolutionUnit;
+  XResolution:=IFD.XResolution;
+  YResolution:=IFD.YResolution;
+  RowsPerStrip:=IFD.RowsPerStrip;
+  StripOffsets:=IFD.StripOffsets;
+  StripByteCounts:=IFD.StripByteCounts;
+  SamplesPerPixel:=IFD.SamplesPerPixel;
+  Artist:=IFD.Artist;
+  HostComputer:=IFD.HostComputer;
+  ImageDescription:=IFD.ImageDescription;
+  Make_ScannerManufacturer:=IFD.Make_ScannerManufacturer;
+  Model_Scanner:=IFD.Model_Scanner;
+  Copyright:=IFD.Copyright;
+  DateAndTime:=IFD.DateAndTime;
+  Software:=IFD.Software;
+  CellWidth:=IFD.CellWidth;
+  CellLength:=IFD.CellLength;
+  FillOrder:=IFD.FillOrder;
+  Orientation:=IFD.Orientation;
+  PageNumber:=IFD.PageNumber;
+  PageCount:=IFD.PageCount;
+  PageName:=IFD.PageName;
+
+  // tiles
+  TileWidth:=IFD.TileWidth;
+  TileLength:=IFD.TileLength;
+  TileOffsets:=IFD.TileOffsets;
+  TileByteCounts:=IFD.TileByteCounts;
+
+  Tresholding:=IFD.Tresholding;
+
+  RedBits:=IFD.RedBits;
+  GreenBits:=IFD.GreenBits;
+  BlueBits:=IFD.BlueBits;
+  GrayBits:=IFD.GrayBits;
+  AlphaBits:=IFD.AlphaBits;
+  if (Img<>nil) and (IFD.Img<>nil) then
+    Img.Assign(IFD.Img);
+end;
+
+procedure TTiffIFD.ReadFPImgExtras(Src: TFPCustomImage);
+begin
+  Clear;
+  PhotoMetricInterpretation:=2;
+  if Src.Extra[TiffPhotoMetric]<>'' then
+    PhotoMetricInterpretation:=
+      StrToInt64Def(Src.Extra[TiffPhotoMetric],High(PhotoMetricInterpretation));
+  Artist:=Src.Extra[TiffArtist];
+  Copyright:=Src.Extra[TiffCopyright];
+  DocumentName:=Src.Extra[TiffDocumentName];
+  DateAndTime:=Src.Extra[TiffDateTime];
+  HostComputer:=Src.Extra[TiffHostComputer];
+  Make_ScannerManufacturer:=Src.Extra[TiffMake_ScannerManufacturer];
+  Model_Scanner:=Src.Extra[TiffModel_Scanner];
+  ImageDescription:=Src.Extra[TiffImageDescription];
+  Software:=Src.Extra[TiffSoftware];
+  Orientation:=StrToIntDef(Src.Extra[TiffOrientation],1);
+  if not (Orientation in [1..8]) then
+    Orientation:=1;
+  ResolutionUnit:=StrToIntDef(Src.Extra[TiffResolutionUnit],2);
+  if not (ResolutionUnit in [1..3]) then
+    ResolutionUnit:=2;
+  XResolution:=StrToTiffRationalDef(Src.Extra[TiffXResolution],TiffRational72);
+  YResolution:=StrToTiffRationalDef(Src.Extra[TiffYResolution],TiffRational72);
+  PageNumber:=StrToIntDef(Src.Extra[TiffPageNumber],0);
+  PageCount:=StrToIntDef(Src.Extra[TiffPageCount],0);
+  PageName:=Src.Extra[TiffPageName];
+  ImageIsPage:=PageCount>0;
+  ImageIsThumbNail:=Src.Extra[TiffIsThumbnail]<>'';
+  ImageIsMask:=Src.Extra[TiffIsMask]<>'';
+  TileWidth:=StrToIntDef(Src.Extra[TiffTileWidth],0);
+  TileLength:=StrToIntDef(Src.Extra[TiffTileLength],0);
+  Compression:=StrToIntDef(Src.Extra[TiffCompression],TiffCompressionNone);
+end;
+
+function TTiffIFD.ImageLength: DWord;
+begin
+  Result:=ImageHeight;
 end;
 
-procedure TTiffIDF.Assign(IDF: TTiffIDF);
+destructor TTiffIFD.Destroy;
 begin
-  PhotoMetricInterpretation:=IDF.PhotoMetricInterpretation;
-  PlanarConfiguration:=IDF.PlanarConfiguration;
-  Compression:=IDF.Compression;
-  Predictor:=IDF.Predictor;
-  ImageHeight:=IDF.ImageHeight;
-  ImageWidth:=IDF.ImageWidth;
-  ImageIsThumbNail:=IDF.ImageIsThumbNail;
-  ImageIsPage:=IDF.ImageIsPage;
-  ImageIsMask:=IDF.ImageIsMask;
-  BitsPerSample:=IDF.BitsPerSample;
-  BitsPerSampleArray:=IDF.BitsPerSampleArray;
-  ResolutionUnit:=IDF.ResolutionUnit;
-  XResolution:=IDF.XResolution;
-  YResolution:=IDF.YResolution;
-  RowsPerStrip:=IDF.RowsPerStrip;
-  StripOffsets:=IDF.StripOffsets;
-  StripByteCounts:=IDF.StripByteCounts;
-  SamplesPerPixel:=IDF.SamplesPerPixel;
-  Artist:=IDF.Artist;
-  HostComputer:=IDF.HostComputer;
-  ImageDescription:=IDF.ImageDescription;
-  Make_ScannerManufacturer:=IDF.Make_ScannerManufacturer;
-  Model_Scanner:=IDF.Model_Scanner;
-  Copyright:=IDF.Copyright;
-  DateAndTime:=IDF.DateAndTime;
-  Software:=IDF.Software;
-  CellWidth:=IDF.CellWidth;
-  CellLength:=IDF.CellLength;
-  FillOrder:=IDF.FillOrder;
-  Orientation:=IDF.Orientation;
-  Treshholding:=IDF.Treshholding;
-  RedBits:=IDF.RedBits;
-  GreenBits:=IDF.GreenBits;
-  BlueBits:=IDF.BlueBits;
-  GrayBits:=IDF.GrayBits;
-  AlphaBits:=IDF.AlphaBits;
-  if (Img<>nil) and (IDF.Img<>nil) then
-    Img.Assign(IDF.Img);
+  if FreeImg then
+    FreeAndNil(Img);
+  inherited Destroy;
 end;
 
 end.

+ 1 - 0
packages/fcl-image/src/fpwritepng.pp

@@ -449,6 +449,7 @@ begin
   // signature for PNG
   TheStream.writeBuffer(Signature,sizeof(Signature));
   // Determine all settings for filling the header
+  fillchar(fheader,sizeof(fheader),#0);
   DetermineHeader (FHeader);
   // write the header chunk
   SetChunkLength (13);   // (sizeof(FHeader)); gives 14 and is wrong !!

+ 477 - 289
packages/fcl-image/src/fpwritetiff.pas

@@ -1,8 +1,8 @@
 {
     This file is part of the Free Pascal run time library.
-    Copyright (c) 2008 by the Free Pascal development team
+    Copyright (c) 2012 by the Free Pascal development team
 
-    Tiff reader for fpImage.
+    Tiff writer for fpImage.
 
     See the file COPYING.FPC, included in this distribution,
     for details about the copyright.
@@ -13,39 +13,38 @@
 
  **********************************************************************
 
-  Working:
-    Grayscale 8,16bit (optional alpha),
-    RGB 8,16bit (optional alpha),
-    Orientation,
-
-  ToDo:
-    Compression: LZW, packbits, deflate, jpeg, ...
-    thumbnail
-    Planar
-    ColorMap
-    multiple images
-    separate mask
-    pages
-    fillorder - not needed by baseline tiff reader
-    bigtiff 64bit offsets
-    endian - currently using system endianess
+ Working:
+   Grayscale 8,16bit (optional alpha),
+   RGB 8,16bit (optional alpha),
+   Orientation,
+   multiple images, pages
+   thumbnail
+   Compression: deflate
+
+ ToDo:
+   Compression: LZW, packbits, jpeg, ...
+   Planar
+   ColorMap
+   separate mask
+   fillorder - not needed by baseline tiff reader
+   bigtiff 64bit offsets
+   endian - currently using system endianess
+   orientation with rotation
 }
 unit FPWriteTiff;
 
 {$mode objfpc}{$H+}
 
-{off $DEFINE VerboseTiffWriter}
-
 interface
 
 uses
-  Math, Classes, SysUtils, FPimage, FPTiffCmn;
+  Math, Classes, SysUtils, zbase, zdeflate, FPimage, FPTiffCmn;
 
 type
 
-  { TTiffWriteEntry }
+  { TTiffWriterEntry }
 
-  TTiffWriteEntry = class
+  TTiffWriterEntry = class
   public
     Tag: Word;
     EntryType: Word;
@@ -56,19 +55,19 @@ type
     destructor Destroy; override;
   end;
 
-  TTiffWriteStrip = record
+  TTiffWriterChunk = record
     Data: Pointer;
     Bytes: DWord;
   end;
-  PTiffWriteStrip = ^TTiffWriteStrip;
+  PTiffWriterChunk = ^TTiffWriterChunk;
 
-  { TTiffWriteStripOffsets }
+  { TTiffWriterChunkOffsets }
 
-  TTiffWriteStripOffsets = class(TTiffWriteEntry)
+  TTiffWriterChunkOffsets = class(TTiffWriterEntry)
   public
-    Strips: PTiffWriteStrip;
-    StripByteCounts: TTiffWriteEntry;
-    constructor Create;
+    Chunks: PTiffWriterChunk;
+    ChunkByteCounts: TTiffWriterEntry;
+    constructor Create(ChunkType: TTiffChunkType);
     destructor Destroy; override;
     procedure SetCount(NewCount: DWord);
   end;
@@ -79,16 +78,16 @@ type
   private
     FSaveCMYKAsRGB: boolean;
     fStartPos: Int64;
-    FEntries: TFPList; // list of TFPList of TTiffWriteEntry
+    FEntries: TFPList; // list of TFPList of TTiffWriterEntry
     fStream: TStream;
     fPosition: DWord;
     procedure ClearEntries;
     procedure WriteTiff;
     procedure WriteHeader;
-    procedure WriteIDFs;
-    procedure WriteEntry(Entry: TTiffWriteEntry);
+    procedure WriteIFDs;
+    procedure WriteEntry(Entry: TTiffWriterEntry);
     procedure WriteData;
-    procedure WriteEntryData(Entry: TTiffWriteEntry);
+    procedure WriteEntryData(Entry: TTiffWriterEntry);
     procedure WriteBuf(var Buf; Count: DWord);
     procedure WriteWord(w: Word);
     procedure WriteDWord(d: DWord);
@@ -97,12 +96,14 @@ type
     procedure AddEntryString(Tag: word; const s: string);
     procedure AddEntryShort(Tag: word; Value: Word);
     procedure AddEntryLong(Tag: word; Value: DWord);
+    procedure AddEntryShortOrLong(Tag: word; Value: DWord);
     procedure AddEntryRational(Tag: word; const Value: TTiffRational);
     procedure AddEntry(Tag: Word; EntryType: Word; EntryCount: DWord;
                        Data: Pointer; Bytes: DWord;
                        CopyData: boolean = true);
-    procedure AddEntry(Entry: TTiffWriteEntry);
+    procedure AddEntry(Entry: TTiffWriterEntry);
     procedure TiffError(Msg: string);
+    procedure EncodeDeflate(var Buffer: Pointer; var Count: DWord);
   public
     constructor Create; override;
     destructor Destroy; override;
@@ -114,11 +115,94 @@ type
 
 function CompareTiffWriteEntries(Entry1, Entry2: Pointer): integer;
 
+function CompressDeflate(InputData: PByte; InputCount: cardinal;
+  out Compressed: PByte; var CompressedCount: cardinal;
+  ErrorMsg: PAnsiString = nil): boolean;
+
 implementation
 
 function CompareTiffWriteEntries(Entry1, Entry2: Pointer): integer;
 begin
-  Result:=integer(TTiffWriteEntry(Entry1).Tag)-integer(TTiffWriteEntry(Entry2).Tag);
+  Result:=integer(TTiffWriterEntry(Entry1).Tag)-integer(TTiffWriterEntry(Entry2).Tag);
+end;
+
+function CompressDeflate(InputData: PByte; InputCount: cardinal; out
+  Compressed: PByte; var CompressedCount: cardinal; ErrorMsg: PAnsiString
+  ): boolean;
+var
+  stream : z_stream;
+  err : integer;
+begin
+  Result:=false;
+  //writeln('CompressDeflate START');
+  Compressed:=nil;
+  if InputCount=0 then begin
+    CompressedCount:=0;
+    exit(true);
+  end;
+
+  err := deflateInit(stream{%H-}, Z_DEFAULT_COMPRESSION);
+  if err <> Z_OK then begin
+    if ErrorMsg<>nil then
+      ErrorMsg^:='deflateInit failed';
+    exit;
+  end;
+
+  // set input = InputData data
+  stream.avail_in := InputCount;
+  stream.next_in  := InputData;
+
+  // set output = compressed data
+  if CompressedCount=0 then
+    CompressedCount:=InputCount;
+  GetMem(Compressed,CompressedCount);
+  stream.avail_out := CompressedCount;
+  stream.next_out := Compressed;
+
+  err := deflate(stream, Z_NO_FLUSH);
+  if err<>Z_OK then begin
+    if ErrorMsg<>nil then
+      ErrorMsg^:='deflate failed';
+    exit;
+  end;
+
+  while TRUE do begin
+    //writeln('run: total_in=',stream.total_in,' avail_in=',stream.avail_in,' total_out=',stream.total_out,' avail_out=',stream.avail_out);
+    if (stream.avail_out=0) then begin
+      // need more space
+      if CompressedCount<128 then
+        CompressedCount:=CompressedCount+128
+      else if CompressedCount>High(CompressedCount)-1024 then begin
+        if ErrorMsg<>nil then
+          ErrorMsg^:='deflate compression failed, because not enough space';
+        exit;
+      end else
+        CompressedCount:=CompressedCount+1024;
+      ReAllocMem(Compressed,CompressedCount);
+      stream.next_out:=Compressed+stream.total_out;
+      stream.avail_out:=CompressedCount-stream.total_out;
+    end;
+    err := deflate(stream, Z_FINISH);
+    if err = Z_STREAM_END then
+      break;
+    if err<>Z_OK then begin
+      if ErrorMsg<>nil then
+        ErrorMsg^:='deflate finish failed';
+      exit;
+    end;
+  end;
+
+  //writeln('compressed: total_in=',stream.total_in,' total_out=',stream.total_out);
+  CompressedCount:=stream.total_out;
+  ReAllocMem(Compressed,CompressedCount);
+
+  err := deflateEnd(stream);
+  if err<>Z_OK then begin
+    if ErrorMsg<>nil then
+      ErrorMsg^:='deflateEnd failed';
+    exit;
+  end;
+  Result:=true;
 end;
 
 { TFPWriterTiff }
@@ -154,12 +238,12 @@ end;
 
 procedure TFPWriterTiff.WriteTiff;
 begin
-  {$IFDEF VerboseTiffWriter}
+  {$IFDEF FPC_Debug_Image}
   writeln('TFPWriterTiff.WriteTiff fStream=',fStream<>nil);
   {$ENDIF}
   fPosition:=0;
   WriteHeader;
-  WriteIDFs;
+  WriteIFDs;
   WriteData;
 end;
 
@@ -173,41 +257,41 @@ begin
   WriteDWord(8);
 end;
 
-procedure TFPWriterTiff.WriteIDFs;
+procedure TFPWriterTiff.WriteIFDs;
 var
   i: Integer;
   List: TFPList;
   j: Integer;
-  Entry: TTiffWriteEntry;
-  NextIDFPos: DWord;
+  Entry: TTiffWriterEntry;
+  NextIFDPos: DWord;
 begin
   for i:=0 to FEntries.Count-1 do begin
     List:=TFPList(FEntries[i]);
     // write count
-    {$IFDEF VerboseTiffWriter}
-    writeln('TFPWriterTiff.WriteIDFs Count=',List.Count);
+    {$IFDEF FPC_Debug_Image}
+    writeln('TFPWriterTiff.WriteIFDs List=',i,' Count=',List.Count);
     {$ENDIF}
     WriteWord(List.Count);
     // write array of entries
     for j:=0 to List.Count-1 do begin
-      Entry:=TTiffWriteEntry(List[j]);
+      Entry:=TTiffWriterEntry(List[j]);
       WriteEntry(Entry);
     end;
-    // write position of next IDF
+    // write position of next IFD
     if i<FEntries.Count-1 then
-      NextIDFPos:=fPosition+4
+      NextIFDPos:=fPosition+4
     else
-      NextIDFPos:=0;
-    WriteDWord(NextIDFPos);
+      NextIFDPos:=0;
+    WriteDWord(NextIFDPos);
   end;
 end;
 
-procedure TFPWriterTiff.WriteEntry(Entry: TTiffWriteEntry);
+procedure TFPWriterTiff.WriteEntry(Entry: TTiffWriterEntry);
 var
   PadBytes: DWord;
 begin
-  {$IFDEF VerboseTiffWriter}
-  writeln('TFPWriterTiff.WriteEntry Tag=',Entry.Tag,' Type=',Entry.EntryType,' Count=',Entry.Count,' Bytes=',Entry.Bytes);
+  {$IFDEF FPC_Debug_Image}
+  //writeln('TFPWriterTiff.WriteEntry Tag=',Entry.Tag,' Type=',Entry.EntryType,' Count=',Entry.Count,' Bytes=',Entry.Bytes);
   {$ENDIF}
   WriteWord(Entry.Tag);
   WriteWord(Entry.EntryType);
@@ -227,8 +311,8 @@ var
   i: Integer;
   List: TFPList;
   j: Integer;
-  Entry: TTiffWriteEntry;
-  Strips: TTiffWriteStripOffsets;
+  Entry: TTiffWriterEntry;
+  Chunks: TTiffWriterChunkOffsets;
   k: Integer;
   Bytes: DWord;
 begin
@@ -236,31 +320,31 @@ begin
     List:=TFPList(FEntries[i]);
     // write entry data
     for j:=0 to List.Count-1 do begin
-      Entry:=TTiffWriteEntry(List[j]);
+      Entry:=TTiffWriterEntry(List[j]);
       WriteEntryData(Entry);
     end;
-    // write strips
+    // write Chunks
     for j:=0 to List.Count-1 do begin
-      Entry:=TTiffWriteEntry(List[j]);
-      if Entry is TTiffWriteStripOffsets then begin
-        Strips:=TTiffWriteStripOffsets(Entry);
-        // write Strips
-        for k:=0 to Strips.Count-1 do begin
-          PDWord(Strips.Data)[k]:=fPosition;
-          Bytes:=Strips.Strips[k].Bytes;
-          PDWord(Strips.StripByteCounts.Data)[k]:=Bytes;
-          {$IFDEF VerboseTiffWriter}
-          //writeln('TFPWriterTiff.WriteData Strip fPosition=',fPosition,' Bytes=',Bytes);
+      Entry:=TTiffWriterEntry(List[j]);
+      if Entry is TTiffWriterChunkOffsets then begin
+        Chunks:=TTiffWriterChunkOffsets(Entry);
+        // write Chunks
+        for k:=0 to Chunks.Count-1 do begin
+          PDWord(Chunks.Data)[k]:=fPosition;
+          Bytes:=Chunks.Chunks[k].Bytes;
+          PDWord(Chunks.ChunkByteCounts.Data)[k]:=Bytes;
+          {$IFDEF FPC_Debug_Image}
+          //writeln('TFPWriterTiff.WriteData Chunk fPosition=',fPosition,' Bytes=',Bytes);
           {$ENDIF}
           if Bytes>0 then
-            WriteBuf(Strips.Strips[k].Data^,Bytes);
+            WriteBuf(Chunks.Chunks[k].Data^,Bytes);
         end;
       end;
     end;
   end;
 end;
 
-procedure TFPWriterTiff.WriteEntryData(Entry: TTiffWriteEntry);
+procedure TFPWriterTiff.WriteEntryData(Entry: TTiffWriterEntry);
 begin
   if Entry.Bytes>4 then begin
     Entry.DataPos:=fPosition;
@@ -278,122 +362,121 @@ end;
 
 procedure TFPWriterTiff.AddImage(Img: TFPCustomImage);
 var
-  IDF: TTiffIDF;
-  GrayBits: Word;
-  RedBits: Word;
-  GreenBits: Word;
-  BlueBits: Word;
-  AlphaBits: Word;
-  ImgWidth: DWord;
-  ImgHeight: DWord;
+  IFD: TTiffIFD;
+  GrayBits, RedBits, GreenBits, BlueBits, AlphaBits: Word;
+  ImgWidth, ImgHeight: DWord;
   Compression: Word;
   BitsPerSample: array[0..3] of Word;
   SamplesPerPixel: Integer;
   BitsPerPixel: DWord;
   i: Integer;
-  OrientedWidth: DWord;
-  OrientedHeight: DWord;
-  y: integer;
-  x: Integer;
-  StripOffsets: TTiffWriteStripOffsets;
-  Row: DWord;
+  OrientedWidth, OrientedHeight: DWord;
   BytesPerLine: DWord;
-  StripBytes: DWord;
-  Strip: PByte;
+  ChunkType: TTiffChunkType;
+  ChunkCount: DWord;
+  ChunkOffsets: TTiffWriterChunkOffsets;
+  ChunkIndex: DWord;
+  ChunkBytes: DWord;
+  Chunk: PByte;
+  ChunkLeft, ChunkTop, ChunkWidth, ChunkHeight: DWord;
+  TilesAcross, TilesDown: DWord;
   Run: PByte;
-  StripIndex: DWord;
   Col: TFPColor;
   Value: Integer;
-  dx: Integer;
-  dy: Integer;
   CurEntries: TFPList;
-  StripCounts: TTiffWriteEntry;
+  Shorts: array[0..3] of Word;
+  NewSubFileType: DWord;
+  cx,cy,x,y,sx: DWord;
+  dx,dy: integer;
+  ChunkBytesPerLine: DWord;
 begin
-  StripOffsets:=nil;
-  Strip:=nil;
-  IDF:=TTiffIDF.Create;
+  ChunkOffsets:=nil;
+  Chunk:=nil;
+  IFD:=TTiffIFD.Create;
   try
     // add new list of entries
     CurEntries:=TFPList.Create;
     FEntries.Add(CurEntries);
 
-    if Img.Extra[TiffPhotoMetric]='' then
-      IDF.PhotoMetricInterpretation:=2
-    else begin
-      IDF.PhotoMetricInterpretation:=StrToInt64Def(Img.Extra[TiffPhotoMetric],High(IDF.PhotoMetricInterpretation));
-      if SaveCMYKAsRGB and (IDF.PhotoMetricInterpretation=5) then
-        IDF.PhotoMetricInterpretation:=2;
-    end;
-    if not (IDF.PhotoMetricInterpretation in [0,1,2]) then
+    IFD.ReadFPImgExtras(Img);
+    if SaveCMYKAsRGB and (IFD.PhotoMetricInterpretation=5) then
+      IFD.PhotoMetricInterpretation:=2;
+    if not (IFD.PhotoMetricInterpretation in [0,1,2]) then
       TiffError('PhotoMetricInterpretation="'+Img.Extra[TiffPhotoMetric]+'" not supported');
-    IDF.Artist:=Img.Extra[TiffArtist];
-    IDF.Copyright:=Img.Extra[TiffCopyright];
-    IDF.DocumentName:=Img.Extra[TiffDocumentName];
-    IDF.DateAndTime:=Img.Extra[TiffDateTime];
-    IDF.ImageDescription:=Img.Extra[TiffImageDescription];
-    IDF.Orientation:=StrToIntDef(Img.Extra[TiffOrientation],1);
-    if not (IDF.Orientation in [1..8]) then
-      IDF.Orientation:=1;
-    IDF.ResolutionUnit:=StrToIntDef(Img.Extra[TiffResolutionUnit],2);
-    if not (IDF.ResolutionUnit in [1..3]) then
-      IDF.ResolutionUnit:=2;
-    IDF.XResolution:=StrToTiffRationalDef(Img.Extra[TiffXResolution],TiffRational72);
-    IDF.YResolution:=StrToTiffRationalDef(Img.Extra[TiffYResolution],TiffRational72);
-
-    GrayBits:=StrToIntDef(Img.Extra[TiffGrayBits],8);
-    RedBits:=StrToIntDef(Img.Extra[TiffRedBits],8);
-    GreenBits:=StrToIntDef(Img.Extra[TiffGreenBits],8);
-    BlueBits:=StrToIntDef(Img.Extra[TiffBlueBits],8);
+
+    GrayBits:=0;
+    RedBits:=0;
+    GreenBits:=0;
+    BlueBits:=0;
+    AlphaBits:=0;
+    case IFD.PhotoMetricInterpretation of
+    0,1:
+      begin
+        GrayBits:=StrToIntDef(Img.Extra[TiffGrayBits],8);
+        BitsPerSample[0]:=GrayBits;
+        SamplesPerPixel:=1;
+      end;
+    2:
+      begin
+        RedBits:=StrToIntDef(Img.Extra[TiffRedBits],8);
+        GreenBits:=StrToIntDef(Img.Extra[TiffGreenBits],8);
+        BlueBits:=StrToIntDef(Img.Extra[TiffBlueBits],8);
+        BitsPerSample[0]:=RedBits;
+        BitsPerSample[1]:=GreenBits;
+        BitsPerSample[2]:=BlueBits;
+        SamplesPerPixel:=3;
+      end;
+    end;
     AlphaBits:=StrToIntDef(Img.Extra[TiffAlphaBits],8);
+    if AlphaBits>0 then begin
+      BitsPerSample[SamplesPerPixel]:=AlphaBits;
+      inc(SamplesPerPixel);
+    end;
+
     ImgWidth:=Img.Width;
     ImgHeight:=Img.Height;
-    Compression:=1;
+    Compression:=IFD.Compression;
+    case Compression of
+    TiffCompressionNone,
+    TiffCompressionDeflateZLib: ;
+    else
+      {$ifdef FPC_DEBUG_IMAGE}
+      writeln('TFPWriterTiff.AddImage unsupported compression '+TiffCompressionName(Compression)+', using deflate instead.');
+      {$endif}
+      Compression:=TiffCompressionDeflateZLib;
+    end;
 
-    if IDF.Orientation in [1..4] then begin
+    if IFD.Orientation in [1..4] then begin
       OrientedWidth:=ImgWidth;
       OrientedHeight:=ImgHeight;
     end else begin
+      // rotated
       OrientedWidth:=ImgHeight;
       OrientedHeight:=ImgWidth;
     end;
 
-    {$IFDEF VerboseTiffWriter}
-    writeln('TFPWriterTiff.AddImage PhotoMetricInterpretation=',IDF.PhotoMetricInterpretation);
+    {$IFDEF FPC_Debug_Image}
+    writeln('TFPWriterTiff.AddImage PhotoMetricInterpretation=',IFD.PhotoMetricInterpretation);
     writeln('TFPWriterTiff.AddImage ImageWidth=',ImgWidth,' ImageHeight=',ImgHeight);
-    writeln('TFPWriterTiff.AddImage Orientation=',IDF.Orientation);
-    writeln('TFPWriterTiff.AddImage ResolutionUnit=',IDF.ResolutionUnit);
-    writeln('TFPWriterTiff.AddImage XResolution=',TiffRationalToStr(IDF.XResolution));
-    writeln('TFPWriterTiff.AddImage YResolution=',TiffRationalToStr(IDF.YResolution));
+    writeln('TFPWriterTiff.AddImage Orientation=',IFD.Orientation);
+    writeln('TFPWriterTiff.AddImage ResolutionUnit=',IFD.ResolutionUnit);
+    writeln('TFPWriterTiff.AddImage XResolution=',TiffRationalToStr(IFD.XResolution));
+    writeln('TFPWriterTiff.AddImage YResolution=',TiffRationalToStr(IFD.YResolution));
     writeln('TFPWriterTiff.AddImage GrayBits=',GrayBits,' RedBits=',RedBits,' GreenBits=',GreenBits,' BlueBits=',BlueBits,' AlphaBits=',AlphaBits);
-    writeln('TFPWriterTiff.AddImage Compression=',Compression);
+    writeln('TFPWriterTiff.AddImage Compression=',TiffCompressionName(Compression));
+    writeln('TFPWriterTiff.AddImage Page=',IFD.PageNumber,'/',IFD.PageCount);
     {$ENDIF}
 
     // required meta entries
-    AddEntryShort(262,IDF.PhotoMetricInterpretation);
-    AddEntryLong(256,ImgWidth);
-    AddEntryLong(257,ImgHeight);
+    AddEntryShortOrLong(256,ImgWidth);
+    AddEntryShortOrLong(257,ImgHeight);
     AddEntryShort(259,Compression);
-    AddEntryShort(274,IDF.Orientation);
-    AddEntryShort(296,IDF.ResolutionUnit);
-    AddEntryRational(282,IDF.XResolution);
-    AddEntryRational(283,IDF.YResolution);
-    case IDF.PhotoMetricInterpretation of
-    0,1:
-      begin
-        BitsPerSample[0]:=GrayBits;
-        SamplesPerPixel:=1;
-      end;
-    2:
-      begin
-        BitsPerSample[0]:=RedBits;
-        BitsPerSample[1]:=GreenBits;
-        BitsPerSample[2]:=BlueBits;
-        SamplesPerPixel:=3;
-      end;
-    end;
+    AddEntryShort(262,IFD.PhotoMetricInterpretation);
+    AddEntryShort(274,IFD.Orientation);
+    AddEntryShort(296,IFD.ResolutionUnit);
+    AddEntryRational(282,IFD.XResolution);
+    AddEntryRational(283,IFD.YResolution);
     if AlphaBits>0 then begin
-      BitsPerSample[SamplesPerPixel]:=AlphaBits;
-      inc(SamplesPerPixel);
       // ExtraSamples
       AddEntryShort(338,2);// 2=unassociated alpha
     end;
@@ -401,141 +484,206 @@ begin
     AddEntry(258,3,SamplesPerPixel,@BitsPerSample[0],SamplesPerPixel*2);
     AddEntryShort(277,SamplesPerPixel);
 
-    // RowsPerStrip (required)
+    // BitsPerPixel, BytesPerLine
     BitsPerPixel:=0;
     for i:=0 to SamplesPerPixel-1 do
       inc(BitsPerPixel,BitsPerSample[i]);
     BytesPerLine:=(BitsPerPixel*OrientedWidth+7) div 8;
-    if OrientedWidth=0 then
-      IDF.RowsPerStrip:=8
-    else
-      IDF.RowsPerStrip:=8192 div BytesPerLine;
-    if IDF.RowsPerStrip<1 then
-      IDF.RowsPerStrip:=1;
-    {$IFDEF VerboseTiffWriter}
-    writeln('TFPWriterTiff.AddImage BitsPerPixel=',BitsPerPixel,' OrientedWidth=',OrientedWidth,' BytesPerLine=',BytesPerLine,' RowsPerStrip=',IDF.RowsPerStrip);
-    {$ENDIF}
-    AddEntryLong(278,IDF.RowsPerStrip);
 
     // optional entries
-    if IDF.Artist<>'' then
-      AddEntryString(315,IDF.Artist);
-    if IDF.Copyright<>'' then
-      AddEntryString(33432,IDF.Copyright);
-    if IDF.DocumentName<>'' then
-      AddEntryString(269,IDF.DocumentName);
-    if IDF.DateAndTime<>'' then
-      AddEntryString(306,IDF.DateAndTime);
-    if IDF.ImageDescription<>'' then
-      AddEntryString(270,IDF.ImageDescription);
-
-    // StripOffsets: StripOffsets, StripByteCounts
-    StripOffsets:=TTiffWriteStripOffsets.Create;
-    AddEntry(StripOffsets);
-    StripCounts:=TTiffWriteEntry.Create;
-    StripCounts.Tag:=279;
-    StripCounts.EntryType:=4;
-    StripOffsets.StripByteCounts:=StripCounts;
-    AddEntry(StripCounts);
-    if OrientedHeight>0 then begin
-      StripOffsets.SetCount((OrientedHeight+IDF.RowsPerStrip-1) div IDF.RowsPerStrip);
-      // compute StripOffsets
-      Row:=0;
-      StripIndex:=0;
-      dx:=0;
-      dy:=0;
-      for y:=0 to OrientedHeight-1 do begin
-        if Row=0 then begin
-          // allocate Strip for the next rows
-          StripBytes:=Min(IDF.RowsPerStrip,OrientedHeight-y)*BytesPerLine;
-          //writeln('TFPWriterTiff.AddImage StripIndex=',StripIndex,' StripBytes=',StripBytes);
-          GetMem(Strip,StripBytes);
-          FillByte(Strip^,StripBytes,0);
-          StripOffsets.Strips[StripIndex].Data:=Strip;
-          StripOffsets.Strips[StripIndex].Bytes:=StripBytes;
-          inc(StripIndex);
-          Run:=Strip;
+    NewSubFileType:=0;
+    if IFD.ImageIsThumbNail then inc(NewSubFileType,1);
+    if IFD.ImageIsPage then inc(NewSubFileType,2);
+    if IFD.ImageIsMask then inc(NewSubFileType,4);
+    if NewSubFileType>0 then
+      AddEntryLong(254,NewSubFileType);
+    if IFD.DocumentName<>'' then
+      AddEntryString(269,IFD.DocumentName);
+    if IFD.ImageDescription<>'' then
+      AddEntryString(270,IFD.ImageDescription);
+    if IFD.Make_ScannerManufacturer<>'' then
+      AddEntryString(271,IFD.Make_ScannerManufacturer);
+    if IFD.Model_Scanner<>'' then
+      AddEntryString(272,IFD.Model_Scanner);
+    if IFD.Software<>'' then
+      AddEntryString(305,IFD.Software);
+    if IFD.DateAndTime<>'' then
+      AddEntryString(306,IFD.DateAndTime);
+    if IFD.Artist<>'' then
+      AddEntryString(315,IFD.Artist);
+    if IFD.HostComputer<>'' then
+      AddEntryString(316,IFD.HostComputer);
+    if IFD.PageCount>0 then begin
+      Shorts[0]:=IFD.PageNumber;
+      Shorts[1]:=IFD.PageCount;
+      AddEntry(297,3,2,@Shorts[0],2*SizeOf(Word));
+    end;
+    if IFD.PageName<>'' then
+      AddEntryString(285,IFD.PageName);
+    if IFD.Copyright<>'' then
+      AddEntryString(33432,IFD.Copyright);
+
+    // chunks
+    ChunkType:=tctStrip;
+    if IFD.TileWidth>0 then begin
+      AddEntryShortOrLong(322,IFD.TileWidth);
+      AddEntryShortOrLong(323,IFD.TileLength);
+      ChunkType:=tctTile;
+    end else begin
+      // RowsPerStrip (required)
+      if OrientedWidth=0 then
+        IFD.RowsPerStrip:=8
+      else
+        IFD.RowsPerStrip:=8192 div BytesPerLine;
+      if IFD.RowsPerStrip<1 then
+        IFD.RowsPerStrip:=1;
+      {$IFDEF FPC_Debug_Image}
+      writeln('TFPWriterTiff.AddImage BitsPerPixel=',BitsPerPixel,' OrientedWidth=',OrientedWidth,' BytesPerLine=',BytesPerLine,' RowsPerStrip=',IFD.RowsPerStrip);
+      {$ENDIF}
+      AddEntryShortOrLong(278,IFD.RowsPerStrip);
+    end;
+
+    // tags for Offsets and ByteCounts
+    ChunkOffsets:=TTiffWriterChunkOffsets.Create(ChunkType);
+    AddEntry(ChunkOffsets);
+    AddEntry(ChunkOffsets.ChunkByteCounts);
+    if (OrientedHeight>0) and (OrientedWidth>0) then begin
+      if ChunkType=tctTile then begin
+        TilesAcross:=(OrientedWidth+IFD.TileWidth{%H-}-1) div IFD.TileWidth;
+        TilesDown:=(OrientedHeight+IFD.TileLength{%H-}-1) div IFD.TileLength;
+        ChunkCount:=TilesAcross*TilesDown;
+        {$IFDEF FPC_Debug_Image}
+        writeln('TFPWriterTiff.AddImage BitsPerPixel=',BitsPerPixel,' OrientedWidth=',OrientedWidth,' OrientedHeight=',OrientedHeight,' TileWidth=',IFD.TileWidth,' TileLength=',IFD.TileLength,' TilesAcross=',TilesAcross,' TilesDown=',TilesDown,' ChunkCount=',ChunkCount);
+        {$ENDIF}
+      end else begin
+        ChunkCount:=(OrientedHeight+IFD.RowsPerStrip{%H-}-1) div IFD.RowsPerStrip;
+      end;
+      ChunkOffsets.SetCount(ChunkCount);
+      // create chunks
+      for ChunkIndex:=0 to ChunkCount-1 do begin
+        if ChunkType=tctTile then begin
+          ChunkLeft:=(ChunkIndex mod TilesAcross)*IFD.TileWidth;
+          ChunkTop:=(ChunkIndex div TilesAcross)*IFD.TileLength;
+          ChunkWidth:=Min(IFD.TileWidth,OrientedWidth-ChunkLeft);
+          ChunkHeight:=Min(IFD.TileLength,OrientedHeight-ChunkTop);
+          // boundary tiles are padded to a full tile
+          // the padding is filled with 0 and compression will get rid of it
+          ChunkBytesPerLine:=(BitsPerPixel*IFD.TileWidth+7) div 8;
+          ChunkBytes:=ChunkBytesPerLine*IFD.TileLength;
+        end else begin
+          ChunkLeft:=0;
+          ChunkTop:=IFD.RowsPerStrip*ChunkIndex;
+          ChunkWidth:=OrientedWidth;
+          ChunkHeight:=Min(IFD.RowsPerStrip,OrientedHeight-ChunkTop);
+          ChunkBytesPerLine:=BytesPerLine;
+          ChunkBytes:=ChunkBytesPerLine*ChunkHeight;
         end;
-        // write line
-        for x:=0 to OrientedWidth-1 do begin
-          // Orientation
-          case IDF.Orientation of
-          1: begin dx:=x; dy:=y; end;// 0,0 is left, top
-          2: begin dx:=OrientedWidth-x-1; dy:=y; end;// 0,0 is right, top
-          3: begin dx:=OrientedWidth-x-1; dy:=OrientedHeight-y-1; end;// 0,0 is right, bottom
-          4: begin dx:=x; dy:=OrientedHeight-y; end;// 0,0 is left, bottom
-          5: begin dx:=y; dy:=x; end;// 0,0 is top, left (rotated)
-          6: begin dx:=OrientedHeight-y-1; dy:=x; end;// 0,0 is top, right (rotated)
-          7: begin dx:=OrientedHeight-y-1; dy:=OrientedWidth-x-1; end;// 0,0 is bottom, right (rotated)
-          8: begin dx:=y; dy:=OrientedWidth-x-1; end;// 0,0 is bottom, left (rotated)
+        GetMem(Chunk,ChunkBytes);
+        FillByte(Chunk^,ChunkBytes,0); // fill unused bytes with 0 to help compression
+
+        // Orientation
+        if IFD.Orientation in [1..4] then begin
+          x:=ChunkLeft; y:=ChunkTop;
+          case IFD.Orientation of
+          1: begin dx:=1; dy:=1; end;// 0,0 is left, top
+          2: begin x:=OrientedWidth-x-1; dx:=-1; dy:=1; end;// 0,0 is right, top
+          3: begin x:=OrientedWidth-x-1; dx:=-1; y:=OrientedHeight-y-1; dy:=-1; end;// 0,0 is right, bottom
+          4: begin dx:=1; y:=OrientedHeight-y-1; dy:=-1; end;// 0,0 is left, bottom
           end;
-          Col:=Img.Colors[dx,dy];
-          case IDF.PhotoMetricInterpretation of
-          0,1:
-            begin
-              // grayscale
-              Value:=(DWord(Col.red)+Col.green+Col.blue) div 3;
-              if IDF.PhotoMetricInterpretation=0 then
-                Value:=$ffff-Value;// 0 is white
-              if GrayBits=8 then begin
-                Run^:=Value shr 8;
-                inc(Run);
-              end else if GrayBits=16 then begin
-                PWord(Run)^:=Value;
-                inc(Run,2);
-              end;
-              if AlphaBits=8 then begin
-                Run^:=Col.alpha shr 8;
-                inc(Run);
-              end else if AlphaBits=16 then begin
-                PWord(Run)^:=Col.alpha;
-                inc(Run,2);
-              end;
-            end;
-          2:
-            begin
-              // RGB
-              if RedBits=8 then begin
-                Run^:=Col.red shr 8;
-                inc(Run);
-              end else if RedBits=16 then begin
-                PWord(Run)^:=Col.red;
-                inc(Run,2);
-              end;
-              if GreenBits=8 then begin
-                Run^:=Col.green shr 8;
-                inc(Run);
-              end else if GreenBits=16 then begin
-                PWord(Run)^:=Col.green;
-                inc(Run,2);
-              end;
-              if BlueBits=8 then begin
-                Run^:=Col.blue shr 8;
-                inc(Run);
-              end else if BlueBits=16 then begin
-                PWord(Run)^:=Col.blue;
-                inc(Run,2);
+        end else begin
+          // rotated
+          x:=ChunkTop; y:=ChunkLeft;
+          case IFD.Orientation of
+          5: begin dx:=1; dy:=1; end;// 0,0 is top, left (rotated)
+          6: begin dx:=1; y:=OrientedWidth-y-1; dy:=-1; end;// 0,0 is top, right (rotated)
+          7: begin x:=OrientedHeight-x-1; dx:=-1; y:=OrientedWidth-y-1; dy:=-1; end;// 0,0 is bottom, right (rotated)
+          8: begin x:=OrientedHeight-x-1; dx:=-1; dy:=1; end;// 0,0 is bottom, left (rotated)
+          end;
+        end;
+        //writeln('TFPWriterTiff.AddImage Chunk=',ChunkIndex,'/',ChunkCount,' ChunkBytes=',ChunkBytes,' ChunkRect=',ChunkLeft,',',ChunkTop,',',ChunkWidth,'x',ChunkHeight,' x=',x,' y=',y,' dx=',dx,' dy=',dy);
+        sx:=x; // save start x
+        for cy:=0 to ChunkHeight-1 do begin
+          x:=sx;
+          Run:=Chunk+cy*ChunkBytesPerLine;
+          for cx:=0 to ChunkWidth-1 do begin
+            Col:=Img.Colors[x,y];
+            case IFD.PhotoMetricInterpretation of
+            0,1:
+              begin
+                // grayscale
+                Value:=(DWord(Col.red)+Col.green+Col.blue) div 3;
+                if IFD.PhotoMetricInterpretation=0 then
+                  Value:=$ffff-Value;// 0 is white
+                if GrayBits=8 then begin
+                  Run^:=Value shr 8;
+                  inc(Run);
+                end else if GrayBits=16 then begin
+                  PWord(Run)^:=Value;
+                  inc(Run,2);
+                end;
+                if AlphaBits=8 then begin
+                  Run^:=Col.alpha shr 8;
+                  inc(Run);
+                end else if AlphaBits=16 then begin
+                  PWord(Run)^:=Col.alpha;
+                  inc(Run,2);
+                end;
               end;
-              if AlphaBits=8 then begin
-                Run^:=Col.alpha shr 8;
-                inc(Run);
-              end else if AlphaBits=16 then begin
-                PWord(Run)^:=Col.alpha;
-                inc(Run,2);
+            2:
+              begin
+                // RGB
+                if RedBits=8 then begin
+                  Run^:=Col.red shr 8;
+                  inc(Run);
+                end else if RedBits=16 then begin
+                  PWord(Run)^:=Col.red;
+                  inc(Run,2);
+                end;
+                if GreenBits=8 then begin
+                  Run^:=Col.green shr 8;
+                  inc(Run);
+                end else if GreenBits=16 then begin
+                  PWord(Run)^:=Col.green;
+                  inc(Run,2);
+                end;
+                if BlueBits=8 then begin
+                  Run^:=Col.blue shr 8;
+                  inc(Run);
+                end else if BlueBits=16 then begin
+                  PWord(Run)^:=Col.blue;
+                  inc(Run,2);
+                end;
+                if AlphaBits=8 then begin
+                  Run^:=Col.alpha shr 8;
+                  inc(Run);
+                end else if AlphaBits=16 then begin
+                  PWord(Run)^:=Col.alpha;
+                  inc(Run,2);
+                end;
               end;
             end;
+            // next x
+            inc(x,dx);
           end;
+          // next y
+          inc(y,dy);
         end;
-        // next row
-        inc(Row);
-        if (Row=IDF.RowsPerStrip) then
-          Row:=0;
+
+        // compress
+        case Compression of
+        TiffCompressionDeflateZLib: EncodeDeflate(Chunk,ChunkBytes);
+        end;
+
+        ChunkOffsets.Chunks[ChunkIndex].Data:=Chunk;
+        ChunkOffsets.Chunks[ChunkIndex].Bytes:=ChunkBytes;
+        // next chunk
       end;
+      // created chunks
     end;
 
     CurEntries.Sort(@CompareTiffWriteEntries);
   finally
-    IDF.Free;
+    IFD.Free;
   end;
 end;
 
@@ -575,6 +723,14 @@ begin
   AddEntry(Tag,4,1,@Value,4);
 end;
 
+procedure TFPWriterTiff.AddEntryShortOrLong(Tag: word; Value: DWord);
+begin
+  if Value<=High(Word) then
+    AddEntryShort(Tag,Value)
+  else
+    AddEntryLong(Tag,Value);
+end;
+
 procedure TFPWriterTiff.AddEntryRational(Tag: word; const Value: TTiffRational
   );
 begin
@@ -584,9 +740,9 @@ end;
 procedure TFPWriterTiff.AddEntry(Tag: Word; EntryType: Word; EntryCount: DWord;
   Data: Pointer; Bytes: DWord; CopyData: boolean);
 var
-  Entry: TTiffWriteEntry;
+  Entry: TTiffWriterEntry;
 begin
-  Entry:=TTiffWriteEntry.Create;
+  Entry:=TTiffWriterEntry.Create;
   Entry.Tag:=Tag;
   Entry.EntryType:=EntryType;
   Entry.Count:=EntryCount;
@@ -603,7 +759,7 @@ begin
   AddEntry(Entry);
 end;
 
-procedure TFPWriterTiff.AddEntry(Entry: TTiffWriteEntry);
+procedure TFPWriterTiff.AddEntry(Entry: TTiffWriterEntry);
 var
   List: TFPList;
 begin
@@ -616,6 +772,27 @@ begin
   raise Exception.Create('TFPWriterTiff.TiffError: '+Msg);
 end;
 
+procedure TFPWriterTiff.EncodeDeflate(var Buffer: Pointer; var Count: DWord);
+var
+  NewBuffer: PByte;
+  NewCount: cardinal;
+  ErrorMsg: String;
+begin
+  ErrorMsg:='';
+  NewBuffer:=nil;
+  try
+    NewCount:=Count;
+    if not CompressDeflate(Buffer,Count,NewBuffer,NewCount,@ErrorMsg) then
+      TiffError(ErrorMsg);
+    FreeMem(Buffer);
+    Buffer:=NewBuffer;
+    Count:=NewCount;
+    NewBuffer:=nil;
+  finally
+    ReAllocMem(NewBuffer,0);
+  end;
+end;
+
 constructor TFPWriterTiff.Create;
 begin
   inherited Create;
@@ -635,56 +812,67 @@ begin
   ClearEntries;
 end;
 
-{ TTiffWriteEntry }
+{ TTiffWriterEntry }
 
-destructor TTiffWriteEntry.Destroy;
+destructor TTiffWriterEntry.Destroy;
 begin
   ReAllocMem(Data,0);
   inherited Destroy;
 end;
 
-{ TTiffWriteStripOffsets }
+{ TTiffWriterChunkOffsets }
 
-constructor TTiffWriteStripOffsets.Create;
+constructor TTiffWriterChunkOffsets.Create(ChunkType: TTiffChunkType);
 begin
-  Tag:=273;
-  EntryType:=4;
+  EntryType:=4; // long
+  ChunkByteCounts:=TTiffWriterEntry.Create;
+  ChunkByteCounts.EntryType:=4; // long
+  if ChunkType=tctTile then begin
+    Tag:=324; // TileOffsets
+    ChunkByteCounts.Tag:=325; // TileByteCounts
+  end else begin
+    Tag:=273; // StripOffsets
+    ChunkByteCounts.Tag:=279; // StripByteCounts
+  end;
 end;
 
-destructor TTiffWriteStripOffsets.Destroy;
+destructor TTiffWriterChunkOffsets.Destroy;
 var
   i: Integer;
 begin
-  if Strips<>nil then begin
+  if Chunks<>nil then begin
     for i:=0 to Count-1 do
-      ReAllocMem(Strips[i].Data,0);
-    ReAllocMem(Strips,0);
+      ReAllocMem(Chunks[i].Data,0);
+    ReAllocMem(Chunks,0);
   end;
   inherited Destroy;
 end;
 
-procedure TTiffWriteStripOffsets.SetCount(NewCount: DWord);
+procedure TTiffWriterChunkOffsets.SetCount(NewCount: DWord);
 var
   Size: DWord;
 begin
-  {$IFDEF VerboseTiffWriter}
+  {$IFDEF FPC_Debug_Image}
   writeln('TTiffWriteStripOffsets.SetCount OldCount=',Count,' NewCount=',NewCount);
   {$ENDIF}
   Count:=NewCount;
-  Size:=Count*SizeOf(TTiffWriteStrip);
-  ReAllocMem(Strips,Size);
-  if Size>0 then FillByte(Strips^,Size,0);
+  Size:=Count*SizeOf(TTiffWriterChunk);
+  ReAllocMem(Chunks,Size);
+  if Size>0 then FillByte(Chunks^,Size,0);
   Size:=Count*SizeOf(DWord);
-  // StripOffsets
+  // Offsets
   ReAllocMem(Data,Size);
   if Size>0 then FillByte(Data^,Size,0);
   Bytes:=Size;
-  // StripByteCounts
-  ReAllocMem(StripByteCounts.Data,Size);
-  if Size>0 then FillByte(StripByteCounts.Data^,Size,0);
-  StripByteCounts.Count:=Count;
-  StripByteCounts.Bytes:=Size;
+  // ByteCounts
+  ReAllocMem(ChunkByteCounts.Data,Size);
+  if Size>0 then FillByte(ChunkByteCounts.Data^,Size,0);
+  ChunkByteCounts.Count:=Count;
+  ChunkByteCounts.Bytes:=Size;
 end;
 
+initialization
+  if ImageHandlers.ImageWriter[TiffHandlerName]=nil then
+    ImageHandlers.RegisterImageWriter (TiffHandlerName, 'tif;tiff', TFPWriterTiff);
 end.
 

Some files were not shown because too many files changed in this diff